diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/CMakeLists.txt b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/CgnsGrid.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/CgnsGrid.cpp @@ -0,0 +1,850 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + std::vector pcount( Parallel::nProc, 0 ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zone_pid = iZone % Parallel::nProc; + ZoneState::pids[ iZone ] = zone_pid; + ZoneState::g2lzoneids[ iZone ] = pcount[ zone_pid ]; + pcount[ zone_pid ] ++; + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/CgnsGrid.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Field.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Field.cpp new file mode 100644 index 00000000..659432f8 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Field.cpp @@ -0,0 +1,177 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + r.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + //this->FTCS( zone ); + this->RungeKutta3( zone ); +} + +void Field::FTCS( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->un, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + dt * r[ i ]; + } +} + +void Field::RungeKutta3( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->un, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + dt * r[ i ]; + } +} + +void Field::Rhs( std::vector & u, std::vector & r ) +{ + int ist = 1; + int ied = ni; + + double coef = this->alpha / ( dx * dx ); + + for ( int i = ist; i <= ied; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Field.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Field.h new file mode 100644 index 00000000..965bb327 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Field.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector r; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + void Solve( Zone * zone ); +public: + void FTCS( Zone * zone ); + void RungeKutta3( Zone * zone ); + void Rhs( std::vector & u, std::vector & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/LogFile.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/LogFile.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Parallel.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Parallel.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Parallel.h @@ -0,0 +1,78 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag ); + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXSendChar( field, buffer_size, recv_pid, tag ); +} + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXRecvChar( field, buffer_size, send_pid, tag ); +} + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/README.txt b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/README.txt @@ -0,0 +1,3 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. + +PS D:\github\OneFLOW\example\1d-heat-equation\ftcs\cpp\multiblock\parallel\8blocks\01\build> mpiexec -n 8 .\Debug\testprj.exe diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Solver.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Solver.cpp new file mode 100644 index 00000000..25038559 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Solver.cpp @@ -0,0 +1,680 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = global_zoneid; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + //std::cout << "Parallel::pid = " << Parallel::pid << " "; + //std::cout << "it = " << it << " nt = " << Global::nt << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nsend = -1; + std::vector donordata; + if ( Parallel::pid != send_pid && Parallel::pid != recv_pid ) continue; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( !ZoneState::IsValid( iZone ) && !Parallel::IsServer() ) continue; + + double xmin = 0.0; + double xmax = 0.0; + + if ( ZoneState::IsValid( iZone ) ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Grid * grid = Global::grids[ local_zoneid ]; + int ni = grid->x.size(); + xmin = grid->x[ 0 ]; + xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + } + + HXSendRecvData( &xmin, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + HXSendRecvData( &xmax, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmin = " << xmin << "\n"; + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmax = " << xmax << "\n"; + //} + + if ( Parallel::IsServer() ) + { + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + } + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // for ( int i = 0; i < xmin_list.size(); ++ i ) + // { + // std::cout << "(" << xmin_list[ i ] << "," << xmax_list[ i ] << ") "; + // } + // std::cout << "\n"; + //} + + if ( Parallel::IsServer() ) + { + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[ i ], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[ i ].second ); + } + } + + int kkk = 1; +} + +bool IsLastZone( int iZone ); +bool IsLastZone( int iZone ) +{ + return iZone == ZoneState::nZones - 1; +} + +void Post::AddVector( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + +void Post::GatherField() +{ + this->zoneids.resize( ZoneState::nZones ); + HXBcastData( this->zoneids.data(), this->zoneids.size(), Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Post::GatherField() this->zoneids = \n"; + for ( int i = 0; i < this->zoneids.size(); ++ i ) + { + std::cout << this->zoneids[ i ] << " "; + } + std::cout << "\n"; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + + if ( !ZoneState::IsValid( zoneid ) && !Parallel::IsServer() ) continue; + + int nSize = -1; + std::vector local_x; + std::vector local_u_e; + std::vector local_un; + std::vector local_u; + + if ( Parallel::pid == ZoneState::pids[ zoneid ] ) + { + int local_zoneid = ZoneState::g2lzoneids[ zoneid ]; + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + nSize = local_x.size(); + } + + int send_pid = ZoneState::pids[ zoneid ]; + + HXSendRecvData( &nSize, 1, send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + local_x.resize( nSize ); + local_u_e.resize( nSize ); + local_un.resize( nSize ); + local_u.resize( nSize ); + } + + HXSendRecvData( local_x.data(), local_x.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u_e.data(), local_u_e.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_un.data(), local_un.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u.data(), local_u.size(), send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + this->AddVector( this->x, local_x ); + this->AddVector( this->u_e, local_u_e ); + this->AddVector( this->un, local_un ); + this->AddVector( this->u, local_u ); + } + } +} + +void Post::DumpField() +{ + if ( !Parallel::IsServer() ) return; + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Solver.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Solver.h new file mode 100644 index 00000000..9914c1d7 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); +public: + void AddVector( std::vector & a, std::vector & b ); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/ZoneState.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/ZoneState.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/global.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/global.cpp @@ -0,0 +1,300 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/global.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/heat1d4blocksv1.cgns b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/main.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/plot.py b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/plotting2.jl b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/CMakeLists.txt b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.cpp @@ -0,0 +1,850 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + std::vector pcount( Parallel::nProc, 0 ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zone_pid = iZone % Parallel::nProc; + ZoneState::pids[ iZone ] = zone_pid; + ZoneState::g2lzoneids[ iZone ] = pcount[ zone_pid ]; + pcount[ zone_pid ] ++; + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Field.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Field.cpp new file mode 100644 index 00000000..9afbf451 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Field.cpp @@ -0,0 +1,197 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + u1.resize( ni_total ); + r.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + //this->FTCS( zone ); + this->RungeKutta3( zone ); +} + +void Field::FTCS( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->un, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + dt * r[ i ]; + } +} + +void Field::RungeKutta3( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->un, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u1[ i ] = un[ i ] + dt * r[ i ]; + } + + this->Rhs( this->u1, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u1[ i ] + 0.25 * dt * r[ i ]; + } + + this->Rhs( this->u, this->r ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * r[ i ]; + } + +} + +void Field::Rhs( std::vector & u, std::vector & r ) +{ + int ist = 1; + int ied = ni; + + double coef = this->alpha / ( dx * dx ); + + for ( int i = ist; i <= ied; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Field.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Field.h new file mode 100644 index 00000000..f6e78a8b --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Field.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un, u1; + std::vector r; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + void Solve( Zone * zone ); +public: + void FTCS( Zone * zone ); + void RungeKutta3( Zone * zone ); + void Rhs( std::vector & u, std::vector & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/LogFile.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/LogFile.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Parallel.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Parallel.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Parallel.h @@ -0,0 +1,78 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag ); + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXSendChar( field, buffer_size, recv_pid, tag ); +} + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXRecvChar( field, buffer_size, send_pid, tag ); +} + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/README.txt b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/README.txt @@ -0,0 +1,3 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. + +PS D:\github\OneFLOW\example\1d-heat-equation\ftcs\cpp\multiblock\parallel\8blocks\01\build> mpiexec -n 8 .\Debug\testprj.exe diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Solver.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Solver.cpp new file mode 100644 index 00000000..25038559 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Solver.cpp @@ -0,0 +1,680 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = global_zoneid; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + //std::cout << "Parallel::pid = " << Parallel::pid << " "; + //std::cout << "it = " << it << " nt = " << Global::nt << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nsend = -1; + std::vector donordata; + if ( Parallel::pid != send_pid && Parallel::pid != recv_pid ) continue; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( !ZoneState::IsValid( iZone ) && !Parallel::IsServer() ) continue; + + double xmin = 0.0; + double xmax = 0.0; + + if ( ZoneState::IsValid( iZone ) ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Grid * grid = Global::grids[ local_zoneid ]; + int ni = grid->x.size(); + xmin = grid->x[ 0 ]; + xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + } + + HXSendRecvData( &xmin, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + HXSendRecvData( &xmax, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmin = " << xmin << "\n"; + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmax = " << xmax << "\n"; + //} + + if ( Parallel::IsServer() ) + { + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + } + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // for ( int i = 0; i < xmin_list.size(); ++ i ) + // { + // std::cout << "(" << xmin_list[ i ] << "," << xmax_list[ i ] << ") "; + // } + // std::cout << "\n"; + //} + + if ( Parallel::IsServer() ) + { + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[ i ], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[ i ].second ); + } + } + + int kkk = 1; +} + +bool IsLastZone( int iZone ); +bool IsLastZone( int iZone ) +{ + return iZone == ZoneState::nZones - 1; +} + +void Post::AddVector( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + +void Post::GatherField() +{ + this->zoneids.resize( ZoneState::nZones ); + HXBcastData( this->zoneids.data(), this->zoneids.size(), Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Post::GatherField() this->zoneids = \n"; + for ( int i = 0; i < this->zoneids.size(); ++ i ) + { + std::cout << this->zoneids[ i ] << " "; + } + std::cout << "\n"; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + + if ( !ZoneState::IsValid( zoneid ) && !Parallel::IsServer() ) continue; + + int nSize = -1; + std::vector local_x; + std::vector local_u_e; + std::vector local_un; + std::vector local_u; + + if ( Parallel::pid == ZoneState::pids[ zoneid ] ) + { + int local_zoneid = ZoneState::g2lzoneids[ zoneid ]; + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + nSize = local_x.size(); + } + + int send_pid = ZoneState::pids[ zoneid ]; + + HXSendRecvData( &nSize, 1, send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + local_x.resize( nSize ); + local_u_e.resize( nSize ); + local_un.resize( nSize ); + local_u.resize( nSize ); + } + + HXSendRecvData( local_x.data(), local_x.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u_e.data(), local_u_e.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_un.data(), local_un.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u.data(), local_u.size(), send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + this->AddVector( this->x, local_x ); + this->AddVector( this->u_e, local_u_e ); + this->AddVector( this->un, local_un ); + this->AddVector( this->u, local_u ); + } + } +} + +void Post::DumpField() +{ + if ( !Parallel::IsServer() ) return; + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Solver.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Solver.h new file mode 100644 index 00000000..9914c1d7 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); +public: + void AddVector( std::vector & a, std::vector & b ); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/ZoneState.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/ZoneState.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/global.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/global.cpp @@ -0,0 +1,300 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/global.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/heat1d4blocksv1.cgns b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/main.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/plot.py b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/plotting2.jl b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01a/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/CMakeLists.txt b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.cpp @@ -0,0 +1,850 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + std::vector pcount( Parallel::nProc, 0 ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zone_pid = iZone % Parallel::nProc; + ZoneState::pids[ iZone ] = zone_pid; + ZoneState::g2lzoneids[ iZone ] = pcount[ zone_pid ]; + pcount[ zone_pid ] ++; + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Field.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Field.cpp new file mode 100644 index 00000000..ead20d0f --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Field.cpp @@ -0,0 +1,250 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + u1.resize( ni_total ); + r.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::FTCS( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->un, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + dt * r[ i ]; + } +} + +void Field::RungeKutta( Zone * zone, int istage ) +{ + if ( istage == 0 ) + { + this->RungeKutta3Stage0( zone ); + return; + } + + if ( istage == 1 ) + { + this->RungeKutta3Stage1( zone ); + return; + } + + if ( istage == 2 ) + { + this->RungeKutta3Stage2( zone ); + return; + } +} + +void Field::RungeKutta3Stage0( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->un, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + dt * r[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} + +void Field::UpdateRungeKuttaOldField( int istage ) +{ + if ( istage == 0 ) + { + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->u1[ i ] = this->u[ i ]; + } + return; + } + + if ( istage == 1 ) + { + return; + } + + if ( istage == 2 ) + { + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } + return; + } +} + +void Field::RungeKutta3Stage1( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->u1, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u1[ i ] + 0.25 * dt * r[ i ]; + } +} + +void Field::RungeKutta3Stage2( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->u, this->r ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * r[ i ]; + } +} + + +void Field::Rhs( std::vector & u, std::vector & r ) +{ + int ist = 1; + int ied = ni; + + double coef = this->alpha / ( dx * dx ); + + for ( int i = ist; i <= ied; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Field.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Field.h new file mode 100644 index 00000000..d2ed4c1c --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Field.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un, u1; + std::vector r; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); +public: + void FTCS( Zone * zone ); + void Rhs( std::vector & u, std::vector & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); + void UpdateRungeKuttaOldField( int istage = 0 ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +}; diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/LogFile.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/LogFile.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Parallel.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Parallel.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Parallel.h @@ -0,0 +1,78 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag ); + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXSendChar( field, buffer_size, recv_pid, tag ); +} + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXRecvChar( field, buffer_size, send_pid, tag ); +} + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/README.txt b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/README.txt @@ -0,0 +1,3 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. + +PS D:\github\OneFLOW\example\1d-heat-equation\ftcs\cpp\multiblock\parallel\8blocks\01\build> mpiexec -n 8 .\Debug\testprj.exe diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Solver.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Solver.cpp new file mode 100644 index 00000000..b3830397 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Solver.cpp @@ -0,0 +1,713 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + this->scheme = Scheme::RungeKutta; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = global_zoneid; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + } +} + +void Solver::FTCS() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->FTCS( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } +} + +void Solver::RungeKutta( int istage ) +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->RungeKutta( zone, istage ); + } + this->Boundary(); + this->UpdateRungeKuttaOldField( istage ); +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); +} + +void Solver::UpdateOldField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UpdateRungeKuttaOldField( int istage ) +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateRungeKuttaOldField( istage ); + } +} + +void Solver::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nsend = -1; + std::vector donordata; + if ( Parallel::pid != send_pid && Parallel::pid != recv_pid ) continue; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( !ZoneState::IsValid( iZone ) && !Parallel::IsServer() ) continue; + + double xmin = 0.0; + double xmax = 0.0; + + if ( ZoneState::IsValid( iZone ) ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Grid * grid = Global::grids[ local_zoneid ]; + int ni = grid->x.size(); + xmin = grid->x[ 0 ]; + xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + } + + HXSendRecvData( &xmin, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + HXSendRecvData( &xmax, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + } + + if ( Parallel::IsServer() ) + { + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[ i ], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[ i ].second ); + } + } + + int kkk = 1; +} + +bool IsLastZone( int iZone ); +bool IsLastZone( int iZone ) +{ + return iZone == ZoneState::nZones - 1; +} + +void Post::AddVector( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + +void Post::GatherField() +{ + this->zoneids.resize( ZoneState::nZones ); + HXBcastData( this->zoneids.data(), this->zoneids.size(), Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Post::GatherField() this->zoneids = \n"; + for ( int i = 0; i < this->zoneids.size(); ++ i ) + { + std::cout << this->zoneids[ i ] << " "; + } + std::cout << "\n"; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + + if ( !ZoneState::IsValid( zoneid ) && !Parallel::IsServer() ) continue; + + int nSize = -1; + std::vector local_x; + std::vector local_u_e; + std::vector local_un; + std::vector local_u; + + if ( Parallel::pid == ZoneState::pids[ zoneid ] ) + { + int local_zoneid = ZoneState::g2lzoneids[ zoneid ]; + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + nSize = local_x.size(); + } + + int send_pid = ZoneState::pids[ zoneid ]; + + HXSendRecvData( &nSize, 1, send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + local_x.resize( nSize ); + local_u_e.resize( nSize ); + local_un.resize( nSize ); + local_u.resize( nSize ); + } + + HXSendRecvData( local_x.data(), local_x.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u_e.data(), local_u_e.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_un.data(), local_un.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u.data(), local_u.size(), send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + this->AddVector( this->x, local_x ); + this->AddVector( this->u_e, local_u_e ); + this->AddVector( this->un, local_un ); + this->AddVector( this->u, local_u ); + } + } +} + +void Post::DumpField() +{ + if ( !Parallel::IsServer() ) return; + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Solver.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Solver.h new file mode 100644 index 00000000..59838940 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/Solver.h @@ -0,0 +1,63 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +enum class Scheme +{ + FTCS = 0, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); +public: + void Boundary(); + void UpdateOldField(); + void UpdateRungeKuttaOldField( int istage ); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void RungeKutta(); + void RungeKutta( int istage ); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); +public: + void AddVector( std::vector & a, std::vector & b ); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/ZoneState.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/ZoneState.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/global.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/global.cpp @@ -0,0 +1,300 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/global.h b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/heat1d1block.cgns b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/heat1d1block.cgns differ diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/heat1d4blocksv1.cgns b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/main.cpp b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/plot.py b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/plotting2.jl b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/multiblock/parallel/4blocks/01b/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/CMakeLists.txt b/example/1d-heat-equation/RK3/cpp/singleblock/01/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/CgnsGrid.cpp b/example/1d-heat-equation/RK3/cpp/singleblock/01/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/CgnsGrid.cpp @@ -0,0 +1,850 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + std::vector pcount( Parallel::nProc, 0 ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zone_pid = iZone % Parallel::nProc; + ZoneState::pids[ iZone ] = zone_pid; + ZoneState::g2lzoneids[ iZone ] = pcount[ zone_pid ]; + pcount[ zone_pid ] ++; + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/CgnsGrid.h b/example/1d-heat-equation/RK3/cpp/singleblock/01/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/Field.cpp b/example/1d-heat-equation/RK3/cpp/singleblock/01/Field.cpp new file mode 100644 index 00000000..227bd499 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/Field.cpp @@ -0,0 +1,288 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + u1.resize( ni_total ); + r.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + //this->FTCS( zone ); + this->RungeKutta3( zone ); +} + +void Field::FTCS( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->un, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + dt * r[ i ]; + } +} + +void Field::RungeKutta( Zone * zone, int istage ) +{ + if ( istage == 0 ) + { + this->RungeKutta3Stage0( zone ); + return; + } + + if ( istage == 1 ) + { + this->RungeKutta3Stage1( zone ); + return; + } + + if ( istage == 2 ) + { + this->RungeKutta3Stage2( zone ); + return; + } +} + +void Field::RungeKutta3Stage0( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->un, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + dt * r[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} + +void Field::UpdateRungeKuttaOldField( int istage ) +{ + if ( istage == 0 ) + { + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->u1[ i ] = this->u[ i ]; + } + return; + } + + if ( istage == 1 ) + { + return; + } + + if ( istage == 2 ) + { + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } + return; + } +} + +void Field::RungeKutta3Stage1( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->u1, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u1[ i ] + 0.25 * dt * r[ i ]; + } +} + +void Field::RungeKutta3Stage2( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->u, this->r ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * r[ i ]; + } +} + + +void Field::RungeKutta3( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->un, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u1[ i ] = un[ i ] + dt * r[ i ]; + } + + this->Rhs( this->u1, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u1[ i ] + 0.25 * dt * r[ i ]; + } + + this->Rhs( this->u, this->r ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * r[ i ]; + } + +} + +void Field::Rhs( std::vector & u, std::vector & r ) +{ + int ist = 1; + int ied = ni; + + double coef = this->alpha / ( dx * dx ); + + for ( int i = ist; i <= ied; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/Field.h b/example/1d-heat-equation/RK3/cpp/singleblock/01/Field.h new file mode 100644 index 00000000..122557c3 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/Field.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un, u1; + std::vector r; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + void Solve( Zone * zone ); +public: + void FTCS( Zone * zone ); + void RungeKutta3( Zone * zone ); + void Rhs( std::vector & u, std::vector & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); + void UpdateRungeKuttaOldField( int istage = 0 ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +}; diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/LogFile.cpp b/example/1d-heat-equation/RK3/cpp/singleblock/01/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/LogFile.h b/example/1d-heat-equation/RK3/cpp/singleblock/01/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/Parallel.cpp b/example/1d-heat-equation/RK3/cpp/singleblock/01/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/Parallel.h b/example/1d-heat-equation/RK3/cpp/singleblock/01/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/Parallel.h @@ -0,0 +1,78 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag ); + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXSendChar( field, buffer_size, recv_pid, tag ); +} + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXRecvChar( field, buffer_size, send_pid, tag ); +} + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/README.txt b/example/1d-heat-equation/RK3/cpp/singleblock/01/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/README.txt @@ -0,0 +1,3 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. + +PS D:\github\OneFLOW\example\1d-heat-equation\ftcs\cpp\multiblock\parallel\8blocks\01\build> mpiexec -n 8 .\Debug\testprj.exe diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/Solver.cpp b/example/1d-heat-equation/RK3/cpp/singleblock/01/Solver.cpp new file mode 100644 index 00000000..6388d7d5 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/Solver.cpp @@ -0,0 +1,720 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + //this->SolveMultiZones(); + this->RungeKutta(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d1block.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = global_zoneid; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + //std::cout << "Parallel::pid = " << Parallel::pid << " "; + //std::cout << "it = " << it << " nt = " << Global::nt << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::RungeKutta() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + } +} + +void Solver::RungeKutta( int istage ) +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->RungeKutta( zone, istage ); + } + this->Boundary(); + this->UpdateRungeKuttaOldField( istage ); +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); +} + +void Solver::UpdateOldField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UpdateRungeKuttaOldField( int istage ) +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateRungeKuttaOldField( istage ); + } +} + +void Solver::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nsend = -1; + std::vector donordata; + if ( Parallel::pid != send_pid && Parallel::pid != recv_pid ) continue; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( !ZoneState::IsValid( iZone ) && !Parallel::IsServer() ) continue; + + double xmin = 0.0; + double xmax = 0.0; + + if ( ZoneState::IsValid( iZone ) ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Grid * grid = Global::grids[ local_zoneid ]; + int ni = grid->x.size(); + xmin = grid->x[ 0 ]; + xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + } + + HXSendRecvData( &xmin, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + HXSendRecvData( &xmax, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmin = " << xmin << "\n"; + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmax = " << xmax << "\n"; + //} + + if ( Parallel::IsServer() ) + { + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + } + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // for ( int i = 0; i < xmin_list.size(); ++ i ) + // { + // std::cout << "(" << xmin_list[ i ] << "," << xmax_list[ i ] << ") "; + // } + // std::cout << "\n"; + //} + + if ( Parallel::IsServer() ) + { + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[ i ], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[ i ].second ); + } + } + + int kkk = 1; +} + +bool IsLastZone( int iZone ); +bool IsLastZone( int iZone ) +{ + return iZone == ZoneState::nZones - 1; +} + +void Post::AddVector( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + +void Post::GatherField() +{ + this->zoneids.resize( ZoneState::nZones ); + HXBcastData( this->zoneids.data(), this->zoneids.size(), Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Post::GatherField() this->zoneids = \n"; + for ( int i = 0; i < this->zoneids.size(); ++ i ) + { + std::cout << this->zoneids[ i ] << " "; + } + std::cout << "\n"; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + + if ( !ZoneState::IsValid( zoneid ) && !Parallel::IsServer() ) continue; + + int nSize = -1; + std::vector local_x; + std::vector local_u_e; + std::vector local_un; + std::vector local_u; + + if ( Parallel::pid == ZoneState::pids[ zoneid ] ) + { + int local_zoneid = ZoneState::g2lzoneids[ zoneid ]; + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + nSize = local_x.size(); + } + + int send_pid = ZoneState::pids[ zoneid ]; + + HXSendRecvData( &nSize, 1, send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + local_x.resize( nSize ); + local_u_e.resize( nSize ); + local_un.resize( nSize ); + local_u.resize( nSize ); + } + + HXSendRecvData( local_x.data(), local_x.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u_e.data(), local_u_e.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_un.data(), local_un.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u.data(), local_u.size(), send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + this->AddVector( this->x, local_x ); + this->AddVector( this->u_e, local_u_e ); + this->AddVector( this->un, local_un ); + this->AddVector( this->u, local_u ); + } + } +} + +void Post::DumpField() +{ + if ( !Parallel::IsServer() ) return; + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/Solver.h b/example/1d-heat-equation/RK3/cpp/singleblock/01/Solver.h new file mode 100644 index 00000000..1527dd2b --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/Solver.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void UpdateOldField(); + void UpdateRungeKuttaOldField( int istage ); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void RungeKutta(); + void RungeKutta( int istage ); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); +public: + void AddVector( std::vector & a, std::vector & b ); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/ZoneState.cpp b/example/1d-heat-equation/RK3/cpp/singleblock/01/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/ZoneState.h b/example/1d-heat-equation/RK3/cpp/singleblock/01/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/global.cpp b/example/1d-heat-equation/RK3/cpp/singleblock/01/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/global.cpp @@ -0,0 +1,300 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/global.h b/example/1d-heat-equation/RK3/cpp/singleblock/01/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/heat1d1block.cgns b/example/1d-heat-equation/RK3/cpp/singleblock/01/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/1d-heat-equation/RK3/cpp/singleblock/01/heat1d1block.cgns differ diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/heat1d4blocksv1.cgns b/example/1d-heat-equation/RK3/cpp/singleblock/01/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/RK3/cpp/singleblock/01/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/main.cpp b/example/1d-heat-equation/RK3/cpp/singleblock/01/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/plot.py b/example/1d-heat-equation/RK3/cpp/singleblock/01/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/RK3/cpp/singleblock/01/plotting2.jl b/example/1d-heat-equation/RK3/cpp/singleblock/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/RK3/cpp/singleblock/01/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/RK3/01/rk3.py b/example/1d-heat-equation/RK3/python/01/rk3.py similarity index 100% rename from example/1d-heat-equation/RK3/01/rk3.py rename to example/1d-heat-equation/RK3/python/01/rk3.py diff --git a/example/1d-heat-equation/RK3/02/rk3.py b/example/1d-heat-equation/RK3/python/02/rk3.py similarity index 100% rename from example/1d-heat-equation/RK3/02/rk3.py rename to example/1d-heat-equation/RK3/python/02/rk3.py diff --git a/example/1d-heat-equation/RK3/03/rk3.py b/example/1d-heat-equation/RK3/python/03/rk3.py similarity index 100% rename from example/1d-heat-equation/RK3/03/rk3.py rename to example/1d-heat-equation/RK3/python/03/rk3.py diff --git a/example/1d-heat-equation/ftcs/cpp/01/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/01/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/01/README.txt b/example/1d-heat-equation/ftcs/cpp/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/01/heat1dni81.cgns b/example/1d-heat-equation/ftcs/cpp/01/heat1dni81.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/01/heat1dni81.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/01/main.cpp b/example/1d-heat-equation/ftcs/cpp/01/main.cpp new file mode 100644 index 00000000..6bfa0a0e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01/main.cpp @@ -0,0 +1,320 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename, Grid * grid ); + +class Grid +{ +public: + std::vector x; +}; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void solve() + { + std::cout << "solve()\n"; + Grid grid; + //ReadCgnsGrid( "../heat1d.cgns", &grid ); + ReadCgnsGrid( "../heat1dni81.cgns", &grid ); + int ni = grid.x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid.x; + double dx = x[ 1 ] - x[ 0 ]; + //double dt = 0.0025; + double dt = dx / 10.0; + double t = 1.0; + int nt = static_cast( t / dt )+1; + //int nt = 1; + + std::cout << "nt = " << nt << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + + int icount = 0; + for ( int i = 0; i < ni; ++ i ) + { + std::cout << std::setprecision(15) << un[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + + double alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + double beta = alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << beta << "\n"; + + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + + icount = 0; + for ( int i = 0; i < ni; ++ i ) + { + std::cout << std::setprecision(15) << un[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + + //compute L2 norm of the error + std::vector u_error( ni ); + icount = 0; + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + std::cout << std::setprecision(15) << u_error[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + + icount = 0; + for ( int i = 0; i < ni; ++ i ) + { + std::cout << std::setprecision(15) << u_e[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + int kkk = 1; + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +void ReadCgnsGrid( const std::string & filename, Grid * grid ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/01a/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/01a/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01a/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/01a/README.txt b/example/1d-heat-equation/ftcs/cpp/01a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/01a/heat1dni101.cgns b/example/1d-heat-equation/ftcs/cpp/01a/heat1dni101.cgns new file mode 100644 index 00000000..851c2c3d Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/01a/heat1dni101.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/01a/main.cpp b/example/1d-heat-equation/ftcs/cpp/01a/main.cpp new file mode 100644 index 00000000..fdbe5f1b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01a/main.cpp @@ -0,0 +1,306 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename, Grid * grid ); + +class Grid +{ +public: + std::vector x; +}; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void solve() + { + std::cout << "solve()\n"; + Grid grid; + ReadCgnsGrid( "../heat1dni101.cgns", &grid ); + int ni = grid.x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid.x; + double dx = x[ 1 ] - x[ 0 ]; + double dt = dx / 10.0; + double t = 1.0; + int nt = static_cast( t / dt )+1; + std::cout << "nt = " << nt << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + + double alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + double beta = alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << beta << "\n"; + + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails(u_error); + this->DumpCsvFile("field_final.csv",x,u_e,un,u_error); + + int kkk = 1; + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } + + void DumpErrorDetails( std::vector &u_error ) + { + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + } + + void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) + { + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +void ReadCgnsGrid( const std::string & filename, Grid * grid ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/01a/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/01a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01a/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/01b/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/01b/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01b/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/01b/README.txt b/example/1d-heat-equation/ftcs/cpp/01b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/01b/heat1dni101.cgns b/example/1d-heat-equation/ftcs/cpp/01b/heat1dni101.cgns new file mode 100644 index 00000000..851c2c3d Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/01b/heat1dni101.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/01b/main.cpp b/example/1d-heat-equation/ftcs/cpp/01b/main.cpp new file mode 100644 index 00000000..fdbe5f1b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01b/main.cpp @@ -0,0 +1,306 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename, Grid * grid ); + +class Grid +{ +public: + std::vector x; +}; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void solve() + { + std::cout << "solve()\n"; + Grid grid; + ReadCgnsGrid( "../heat1dni101.cgns", &grid ); + int ni = grid.x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid.x; + double dx = x[ 1 ] - x[ 0 ]; + double dt = dx / 10.0; + double t = 1.0; + int nt = static_cast( t / dt )+1; + std::cout << "nt = " << nt << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + + double alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + double beta = alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << beta << "\n"; + + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails(u_error); + this->DumpCsvFile("field_final.csv",x,u_e,un,u_error); + + int kkk = 1; + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } + + void DumpErrorDetails( std::vector &u_error ) + { + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + } + + void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) + { + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +void ReadCgnsGrid( const std::string & filename, Grid * grid ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/01b/plot.py b/example/1d-heat-equation/ftcs/cpp/01b/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01b/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/01b/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/01b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01b/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/01c/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/01c/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01c/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/01c/README.txt b/example/1d-heat-equation/ftcs/cpp/01c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/01c/heat1d1blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/01c/heat1d1blocksv1.cgns new file mode 100644 index 00000000..470808f4 Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/01c/heat1d1blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/01c/main.cpp b/example/1d-heat-equation/ftcs/cpp/01c/main.cpp new file mode 100644 index 00000000..951a3daf --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01c/main.cpp @@ -0,0 +1,306 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename, Grid * grid ); + +class Grid +{ +public: + std::vector x; +}; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void solve() + { + std::cout << "solve()\n"; + Grid grid; + ReadCgnsGrid( "../heat1d1blocksv1.cgns", &grid ); + int ni = grid.x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid.x; + double dx = x[ 1 ] - x[ 0 ]; + double dt = dx / 10.0; + double t = 1.0; + int nt = static_cast( t / dt )+1; + std::cout << "nt = " << nt << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + + double alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + double beta = alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << beta << "\n"; + + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails(u_error); + this->DumpCsvFile("field_final.csv",x,u_e,un,u_error); + + int kkk = 1; + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } + + void DumpErrorDetails( std::vector &u_error ) + { + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + } + + void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) + { + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +void ReadCgnsGrid( const std::string & filename, Grid * grid ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/01c/plot.py b/example/1d-heat-equation/ftcs/cpp/01c/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01c/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/01c/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/01c/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01c/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/01d/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/01d/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01d/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/01d/README.txt b/example/1d-heat-equation/ftcs/cpp/01d/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01d/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/01d/heat1d1blocksv2.cgns b/example/1d-heat-equation/ftcs/cpp/01d/heat1d1blocksv2.cgns new file mode 100644 index 00000000..1901648a Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/01d/heat1d1blocksv2.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/01d/main.cpp b/example/1d-heat-equation/ftcs/cpp/01d/main.cpp new file mode 100644 index 00000000..c9a2eb81 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01d/main.cpp @@ -0,0 +1,299 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename, Grid * grid ); + +class Grid +{ +public: + std::vector x; +}; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void solve() + { + std::cout << "solve()\n"; + Grid grid; + ReadCgnsGrid( "../heat1d1blocksv2.cgns", &grid ); + int ni = grid.x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid.x; + double dx = std::abs(x[ 1 ] - x[ 0 ]); + double dt = dx / 10.0; + double t = 1.0; + int nt = static_cast( t / dt )+1; + std::cout << "nt = " << nt << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + + double alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + double beta = alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << beta << "\n"; + + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails(u_error); + this->DumpCsvFile("field_final.csv",x,u_e,un,u_error); + + int kkk = 1; + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } + + void DumpErrorDetails( std::vector &u_error ) + { + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + } + + void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) + { + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +void ReadCgnsGrid( const std::string & filename, Grid * grid ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/01d/plot.py b/example/1d-heat-equation/ftcs/cpp/01d/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01d/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/01d/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/01d/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01d/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/01e/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/01e/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01e/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/01e/README.txt b/example/1d-heat-equation/ftcs/cpp/01e/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01e/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/01e/heat1d1blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/01e/heat1d1blocksv3.cgns new file mode 100644 index 00000000..72a50a8e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/01e/heat1d1blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/01e/main.cpp b/example/1d-heat-equation/ftcs/cpp/01e/main.cpp new file mode 100644 index 00000000..5e457a4f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01e/main.cpp @@ -0,0 +1,299 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename, Grid * grid ); + +class Grid +{ +public: + std::vector x; +}; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void solve() + { + std::cout << "solve()\n"; + Grid grid; + ReadCgnsGrid( "../heat1d1blocksv3.cgns", &grid ); + int ni = grid.x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid.x; + double dx = std::abs(x[ 1 ] - x[ 0 ]); + double dt = dx / 10.0; + double t = 1.0; + int nt = static_cast( t / dt )+1; + std::cout << "nt = " << nt << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + + double alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + double beta = alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << beta << "\n"; + + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails(u_error); + this->DumpCsvFile("field_final.csv",x,u_e,un,u_error); + + int kkk = 1; + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } + + void DumpErrorDetails( std::vector &u_error ) + { + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + } + + void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) + { + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +void ReadCgnsGrid( const std::string & filename, Grid * grid ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/01e/plot.py b/example/1d-heat-equation/ftcs/cpp/01e/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01e/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/01e/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/01e/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/01e/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/02/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/02/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/02/README.txt b/example/1d-heat-equation/ftcs/cpp/02/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/02/heat1d2blocks.cgns b/example/1d-heat-equation/ftcs/cpp/02/heat1d2blocks.cgns new file mode 100644 index 00000000..4f4441f0 Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/02/heat1d2blocks.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/02/main.cpp b/example/1d-heat-equation/ftcs/cpp/02/main.cpp new file mode 100644 index 00000000..362f000f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02/main.cpp @@ -0,0 +1,392 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename ); + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ) + { + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + int nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << this->beta << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + } + + void Solve( Grid * grid ) + { + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + } + + void PostProcess( Grid * grid ) + { + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final" + std::to_string( grid->zoneIndex ) + ".csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + void DumpErrorDetails( std::vector &u_error ) + { + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + } + + void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) + { + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +}; + +std::vector Global::grids; +std::vector Global::fields; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void Run() + { + this->ReadGrid(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); + } + + void ReadGrid() + { + ReadCgnsGrid( "../heat1d2blocks.cgns" ); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + } + } + + void InitFields() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = new Field(); + Global::fields.push_back( field ); + field->Init( grid ); + } + } + + void SolveMultiZones() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Solve( grid ); + } + } + + void PostProcess() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->PostProcess( grid ); + } + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } +}; + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.Run(); + //solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/02/plot.py b/example/1d-heat-equation/ftcs/cpp/02/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/02/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/02/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/02a/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/02a/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02a/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/02a/README.txt b/example/1d-heat-equation/ftcs/cpp/02a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/02a/heat1d2blocks.cgns b/example/1d-heat-equation/ftcs/cpp/02a/heat1d2blocks.cgns new file mode 100644 index 00000000..4f4441f0 Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/02a/heat1d2blocks.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/02a/main.cpp b/example/1d-heat-equation/ftcs/cpp/02a/main.cpp new file mode 100644 index 00000000..cd6b53d5 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02a/main.cpp @@ -0,0 +1,506 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename ); +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); +void DumpErrorDetails( std::vector & u_error ); +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ) + { + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + //this->t = 1.0; + this->t = 0.2; + int nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << this->beta << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + } + + void Solve( Grid * grid ) + { + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + } + + void PostProcess( Grid * grid ) + { + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + //this->DumpErrorDetails( u_error ); + + //std::string csvname = "field_final" + std::to_string( grid->zoneIndex ) + ".csv"; + //this->DumpCsvFile( csvname, x, u_e, un, u_error ); + } + + void AddData( Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) + { + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + //void DumpErrorDetails( std::vector &u_error ) + //{ + // int ni = u_error.size(); + // double rms_error = compute_l2norm( ni, u_error ); + // double max_error = compute_max_error( ni, u_error ); + // std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + // //create output file for L2-norm + // std::fstream file; + // file.open("output.txt", std::fstream::out); + // std::format_to(std::ostream_iterator(file), "Error details: \n"); + // std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + // std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + // file.close(); + //} + + //void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) + //{ + // std::fstream file; + // file.open(filename.c_str(), std::fstream::out); + // std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + // for ( int i = 0; i < x.size(); ++ i ) + // { + // std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + // } + // file.close(); + //} + + //double compute_l2norm( int ni, std::vector & r ) + //{ + // double rms = 0.0; + // for ( int i = 1; i < ni - 1; ++ i ) + // { + // rms += r[ i ] * r[ i ]; + // } + // rms = std::sqrt( rms / ( ni - 2 ) ); + // return rms; + //} + + //double compute_max_error( int ni, std::vector & u_error ) + //{ + // double val_max = -1; + // int ipos = -1; + // for ( int i = 1; i < ni - 1; ++ i ) + // { + // //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + // if ( val_max < std::abs( u_error[ i ] ) ) + // { + // ipos = i; + // val_max = std::abs( u_error[ i ] ); + // } + // } + // std::cout << " ipos = " << ipos << "\n"; + // return val_max; + //} +}; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +}; + +std::vector Global::grids; +std::vector Global::fields; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void Run() + { + this->ReadGrid(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); + } + + void ReadGrid() + { + ReadCgnsGrid( "../heat1d2blocks.cgns" ); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + } + } + + void InitFields() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = new Field(); + Global::fields.push_back( field ); + field->Init( grid ); + } + } + + void SolveMultiZones() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Solve( grid ); + } + } + + void PostProcess() + { + int nZones = Global::grids.size(); + std::vector u_e; + std::vector un; + std::vector x; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->AddData( grid, x, u_e, un ); + } + + std::cout << " x.size() = " << x.size() << "\n"; + + PostProcess( x, u_e, un ); + + //for ( int iZone = 0; iZone < nZones; ++ iZone ) + //{ + // Grid * grid = Global::grids[ iZone ]; + // Field * field = Global::fields[ iZone ]; + // field->PostProcess( grid ); + //} + } + + void PostProcess( std::vector &x, std::vector &u_e, std::vector &un ) + { + int ni = x.size(); + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); + } + + //void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) + //{ + // std::fstream file; + // file.open(filename.c_str(), std::fstream::out); + // std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + // for ( int i = 0; i < x.size(); ++ i ) + // { + // std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + // } + // file.close(); + //} + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } +}; + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.Run(); + //solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/02a/plot.py b/example/1d-heat-equation/ftcs/cpp/02a/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02a/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/02a/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/02a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02a/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/02b/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/02b/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02b/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/02b/README.txt b/example/1d-heat-equation/ftcs/cpp/02b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/02b/heat1d2blocks.cgns b/example/1d-heat-equation/ftcs/cpp/02b/heat1d2blocks.cgns new file mode 100644 index 00000000..4f4441f0 Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/02b/heat1d2blocks.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/02b/main.cpp b/example/1d-heat-equation/ftcs/cpp/02b/main.cpp new file mode 100644 index 00000000..32ccdc23 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02b/main.cpp @@ -0,0 +1,834 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); +void DumpErrorDetails( std::vector & u_error ); +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point(const value_type &x) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } + + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid; +class Field; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; + static BaseZoneList zone_names; + static int nt; +}; + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; +BaseZoneList Global::zone_names; +int Global::nt = -1; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ) + { + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + int ist = 0; + int ied = ni - 1; + + // 0(bc) 1(ist) 2 3 ... ni + + //int ist = 0 + 1; + //int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + //un[ ist - 1 ] = 0.0; + //un[ ied + 1 ] = 0.0; + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + } + + void Solve( Grid * grid ) + { + Boundary( grid ); + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + this->update( un, u ); + } + + void Boundary( Grid * grid ) + { + this->InterfaceBoundary( grid ); + this->PhysicalBoundary( grid ); + } + + void PhysicalBoundary( Grid * grid ) + { + BC * bc = Global::bcs[ grid->zoneIndex ]; + + int nBFace = bc->bctypes.size(); + for ( int i = 0; i < nBFace; ++ i ) + { + int bctype = bc->bctypes[ i ]; + int faceId = bc->faceids[ i ]; + if ( bctype == BCInflow ) + { + u[ faceId ] = 0.0; + } + else if ( bctype == BCOutflow ) + { + u[ faceId ] = 0.0; + } + } + } + + void InterfaceBoundary( Grid * grid ) + { + InterFaceZone * interfacezone = Global::interfacezones[ grid->zoneIndex ]; + int nInterfaces = interfacezone->left_u.size(); + for ( int i = 0; i < nInterfaces; ++ i ) + { + double ul = interfacezone->left_u[ i ]; + double ur = interfacezone->right_u[ i ]; + double um = 0.5 * ( ul + ur ); + + int faceId = interfacezone->face_ids[ i ]; + + u[ faceId ] = um; + int kkk = 1; + } + } + + void PostProcess( Grid * grid ) + { + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + } + + void AddData( Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) + { + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } +}; + +class Solver +{ +public: + void Run() + { + this->ReadGrid(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); + } + + void ReadGrid() + { + ReadCgnsGridBaseZone( "../heat1d2blocks.cgns" ); + int kkk = 1; + ReadCgnsGrid( "../heat1d2blocks.cgns" ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point(grid->x[i]) ); + //face.nodes.push_back( pid ); + } + int kkk = 1; + } + } + + void InitFields() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = new Field(); + Global::fields.push_back( field ); + field->Init( grid ); + } + } + + void SolveMultiZones() + { + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceValue(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Solve( grid ); + } + } + } + + void ExchangeInterfaceValue() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } + } + + void PostProcess() + { + int nZones = Global::grids.size(); + std::vector u_e; + std::vector un; + std::vector x; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->AddData( grid, x, u_e, un ); + } + + std::cout << " x.size() = " << x.size() << "\n"; + + this->PostProcess( x, u_e, un ); + } + + void PostProcess( std::vector &x, std::vector &u_e, std::vector &un ) + { + int ni = x.size(); + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + int kkk = 1; + } + } + int kkk = 1; + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/02b/plot.py b/example/1d-heat-equation/ftcs/cpp/02b/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02b/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/02b/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/02b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02b/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/02c/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/02c/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02c/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/02c/README.txt b/example/1d-heat-equation/ftcs/cpp/02c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/02c/heat1d2blocks.cgns b/example/1d-heat-equation/ftcs/cpp/02c/heat1d2blocks.cgns new file mode 100644 index 00000000..4f4441f0 Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/02c/heat1d2blocks.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/02c/main.cpp b/example/1d-heat-equation/ftcs/cpp/02c/main.cpp new file mode 100644 index 00000000..cbfda796 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02c/main.cpp @@ -0,0 +1,860 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); +void DumpErrorDetails( std::vector & u_error ); +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point(const value_type &x) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid; +class Field; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; + static BaseZoneList zone_names; + static int nt; +}; + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; +BaseZoneList Global::zone_names; +int Global::nt = -1; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ) + { + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + int ist = 0; + int ied = ni - 1; + + // 0(bc) 1(ist) 2 3 ... ni + + //int ist = 0 + 1; + //int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + //un[ ist - 1 ] = 0.0; + //un[ ied + 1 ] = 0.0; + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + } + + void Solve( Grid * grid ) + { + Boundary( grid ); + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + this->update( un, u ); + } + + void Boundary( Grid * grid ) + { + this->InterfaceBoundary( grid ); + this->PhysicalBoundary( grid ); + } + + void PhysicalBoundary( Grid * grid ) + { + BC * bc = Global::bcs[ grid->zoneIndex ]; + + int nBFace = bc->bctypes.size(); + for ( int i = 0; i < nBFace; ++ i ) + { + int bctype = bc->bctypes[ i ]; + int faceId = bc->faceids[ i ]; + if ( bctype == BCInflow ) + { + u[ faceId ] = 0.0; + } + else if ( bctype == BCOutflow ) + { + u[ faceId ] = 0.0; + } + } + } + + void InterfaceBoundary( Grid * grid ) + { + InterFaceZone * interfacezone = Global::interfacezones[ grid->zoneIndex ]; + int nInterfaces = interfacezone->left_u.size(); + for ( int i = 0; i < nInterfaces; ++ i ) + { + double ul = interfacezone->left_u[ i ]; + double ur = interfacezone->right_u[ i ]; + double um = 0.5 * ( ul + ur ); + + int faceId = interfacezone->face_ids[ i ]; + + u[ faceId ] = um; + int kkk = 1; + } + } + + void PostProcess( Grid * grid ) + { + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + } + + void AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) + { + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } +}; + +class Solver +{ +public: + void Run() + { + this->ReadGrid(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); + } + + void ReadGrid() + { + ReadCgnsGridBaseZone( "../heat1d2blocks.cgns" ); + int kkk = 1; + ReadCgnsGrid( "../heat1d2blocks.cgns" ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point(grid->x[i]) ); + //face.nodes.push_back( pid ); + } + int kkk = 1; + } + } + + void InitFields() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = new Field(); + Global::fields.push_back( field ); + field->Init( grid ); + } + } + + void SolveMultiZones() + { + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceValue(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Solve( grid ); + } + } + } + + void ExchangeInterfaceValue() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } + } + + void PostProcess() + { + int nZones = Global::grids.size(); + std::vector u_e; + std::vector un; + std::vector x; + + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->AddData( ptfactory, grid, x, u_e, un ); + } + + std::cout << " x.size() = " << x.size() << "\n"; + + this->PostProcess( x, u_e, un ); + } + + void PostProcess( std::vector &x, std::vector &u_e, std::vector &un ) + { + int ni = x.size(); + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + int kkk = 1; + } + } + int kkk = 1; + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/02c/plot.py b/example/1d-heat-equation/ftcs/cpp/02c/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02c/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/02c/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/02c/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/02c/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/03/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/03/CMakeLists.txt new file mode 100644 index 00000000..22d3b209 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/03/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/03/CgnsGrid.cpp new file mode 100644 index 00000000..10c9381e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03/CgnsGrid.cpp @@ -0,0 +1,266 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/03/CgnsGrid.h new file mode 100644 index 00000000..8b188125 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03/CgnsGrid.h @@ -0,0 +1,5 @@ +#pragma once +#include + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03/README.txt b/example/1d-heat-equation/ftcs/cpp/03/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/03/global.cpp b/example/1d-heat-equation/ftcs/cpp/03/global.cpp new file mode 100644 index 00000000..960f3c65 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03/global.cpp @@ -0,0 +1,11 @@ +#include "global.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; +BaseZoneList Global::zone_names; +int Global::nt = -1; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03/global.h b/example/1d-heat-equation/ftcs/cpp/03/global.h new file mode 100644 index 00000000..e0a26c36 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03/global.h @@ -0,0 +1,209 @@ +#pragma once +#include +#include +#include +#include + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point(const value_type &x) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; + static BaseZoneList zone_names; + static int nt; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/03/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/03/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/03/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/03/main.cpp b/example/1d-heat-equation/ftcs/cpp/03/main.cpp new file mode 100644 index 00000000..9ce65500 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03/main.cpp @@ -0,0 +1,383 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Grid; +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); +void DumpErrorDetails( std::vector & u_error ); +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +class Grid; +class Field; + + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ) + { + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + int ist = 0; + int ied = ni - 1; + + // 0(bc) 1(ist) 2 3 ... ni + + //int ist = 0 + 1; + //int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + //un[ ist - 1 ] = 0.0; + //un[ ied + 1 ] = 0.0; + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + } + + void Solve( Grid * grid ) + { + Boundary( grid ); + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + this->update( un, u ); + } + + void Boundary( Grid * grid ) + { + this->InterfaceBoundary( grid ); + this->PhysicalBoundary( grid ); + } + + void PhysicalBoundary( Grid * grid ) + { + BC * bc = Global::bcs[ grid->zoneIndex ]; + + int nBFace = bc->bctypes.size(); + for ( int i = 0; i < nBFace; ++ i ) + { + int bctype = bc->bctypes[ i ]; + int faceId = bc->faceids[ i ]; + if ( bctype == BCInflow ) + { + u[ faceId ] = 0.0; + } + else if ( bctype == BCOutflow ) + { + u[ faceId ] = 0.0; + } + } + } + + void InterfaceBoundary( Grid * grid ) + { + InterFaceZone * interfacezone = Global::interfacezones[ grid->zoneIndex ]; + int nInterfaces = interfacezone->left_u.size(); + for ( int i = 0; i < nInterfaces; ++ i ) + { + double ul = interfacezone->left_u[ i ]; + double ur = interfacezone->right_u[ i ]; + double um = 0.5 * ( ul + ur ); + + int faceId = interfacezone->face_ids[ i ]; + + u[ faceId ] = um; + int kkk = 1; + } + } + + void PostProcess( Grid * grid ) + { + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + } + + void AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) + { + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } +}; + +class Solver +{ +public: + void Run() + { + this->ReadGrid(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); + } + + void ReadGrid() + { + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + int kkk = 1; + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point(grid->x[i]) ); + } + int kkk = 1; + } + } + + void InitFields() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = new Field(); + Global::fields.push_back( field ); + field->Init( grid ); + } + } + + void SolveMultiZones() + { + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceValue(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Solve( grid ); + } + } + } + + void ExchangeInterfaceValue() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } + } + + void PostProcess() + { + int nZones = Global::grids.size(); + std::vector u_e; + std::vector un; + std::vector x; + + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->AddData( ptfactory, grid, x, u_e, un ); + } + + std::cout << " x.size() = " << x.size() << "\n"; + + this->PostProcess( x, u_e, un ); + } + + void PostProcess( std::vector &x, std::vector &u_e, std::vector &un ) + { + int ni = x.size(); + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } +}; + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/03/plot.py b/example/1d-heat-equation/ftcs/cpp/03/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/03/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/03/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/03a/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/03a/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/03a/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/03a/CgnsGrid.cpp new file mode 100644 index 00000000..10c9381e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/CgnsGrid.cpp @@ -0,0 +1,266 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03a/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/03a/CgnsGrid.h new file mode 100644 index 00000000..8b188125 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/CgnsGrid.h @@ -0,0 +1,5 @@ +#pragma once +#include + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03a/Field.cpp b/example/1d-heat-equation/ftcs/cpp/03a/Field.cpp new file mode 100644 index 00000000..63ab0c34 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/Field.cpp @@ -0,0 +1 @@ +#include "Field.h" diff --git a/example/1d-heat-equation/ftcs/cpp/03a/Field.h b/example/1d-heat-equation/ftcs/cpp/03a/Field.h new file mode 100644 index 00000000..9c6cfb64 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/Field.h @@ -0,0 +1,163 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ) + { + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + int ist = 0; + int ied = ni - 1; + + // 0(bc) 1(ist) 2 3 ... ni + + //int ist = 0 + 1; + //int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + //un[ ist - 1 ] = 0.0; + //un[ ied + 1 ] = 0.0; + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + } + + void Solve( Grid * grid ) + { + Boundary( grid ); + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + this->update( un, u ); + } + + void Boundary( Grid * grid ) + { + this->InterfaceBoundary( grid ); + this->PhysicalBoundary( grid ); + } + + void PhysicalBoundary( Grid * grid ) + { + BC * bc = Global::bcs[ grid->zoneIndex ]; + + int nBFace = bc->bctypes.size(); + for ( int i = 0; i < nBFace; ++ i ) + { + int bctype = bc->bctypes[ i ]; + int faceId = bc->faceids[ i ]; + if ( bctype == BCInflow ) + { + u[ faceId ] = 0.0; + } + else if ( bctype == BCOutflow ) + { + u[ faceId ] = 0.0; + } + } + } + + void InterfaceBoundary( Grid * grid ) + { + InterFaceZone * interfacezone = Global::interfacezones[ grid->zoneIndex ]; + int nInterfaces = interfacezone->left_u.size(); + for ( int i = 0; i < nInterfaces; ++ i ) + { + double ul = interfacezone->left_u[ i ]; + double ur = interfacezone->right_u[ i ]; + double um = 0.5 * ( ul + ur ); + + int faceId = interfacezone->face_ids[ i ]; + + u[ faceId ] = um; + int kkk = 1; + } + } + + void PostProcess( Grid * grid ) + { + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + } + + void AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) + { + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03a/README.txt b/example/1d-heat-equation/ftcs/cpp/03a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/03a/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/03a/Solver.cpp new file mode 100644 index 00000000..77b572c6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/Solver.cpp @@ -0,0 +1,57 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03a/Solver.h b/example/1d-heat-equation/ftcs/cpp/03a/Solver.h new file mode 100644 index 00000000..aef7a8a3 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/Solver.h @@ -0,0 +1,153 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); +void DumpErrorDetails( std::vector & u_error ); +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + +class Solver +{ +public: + void Run() + { + this->ReadGrid(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); + } + + void ReadGrid() + { + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + int kkk = 1; + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point(grid->x[i]) ); + } + int kkk = 1; + } + } + + void InitFields() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = new Field(); + Global::fields.push_back( field ); + field->Init( grid ); + } + } + + void SolveMultiZones() + { + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceValue(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Solve( grid ); + } + } + } + + void ExchangeInterfaceValue() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } + } + + void PostProcess() + { + int nZones = Global::grids.size(); + std::vector u_e; + std::vector un; + std::vector x; + + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->AddData( ptfactory, grid, x, u_e, un ); + } + + std::cout << " x.size() = " << x.size() << "\n"; + + this->PostProcess( x, u_e, un ); + } + + void PostProcess( std::vector &x, std::vector &u_e, std::vector &un ) + { + int ni = x.size(); + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03a/global.cpp b/example/1d-heat-equation/ftcs/cpp/03a/global.cpp new file mode 100644 index 00000000..960f3c65 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/global.cpp @@ -0,0 +1,11 @@ +#include "global.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; +BaseZoneList Global::zone_names; +int Global::nt = -1; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03a/global.h b/example/1d-heat-equation/ftcs/cpp/03a/global.h new file mode 100644 index 00000000..e0a26c36 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/global.h @@ -0,0 +1,209 @@ +#pragma once +#include +#include +#include +#include + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point(const value_type &x) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; + static BaseZoneList zone_names; + static int nt; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/03a/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/03a/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/03a/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/03a/main.cpp b/example/1d-heat-equation/ftcs/cpp/03a/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/03a/plot.py b/example/1d-heat-equation/ftcs/cpp/03a/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/03a/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/03a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03a/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/03b/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/03b/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/03b/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/03b/CgnsGrid.cpp new file mode 100644 index 00000000..9afd6e1b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/CgnsGrid.cpp @@ -0,0 +1,383 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03b/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/03b/CgnsGrid.h new file mode 100644 index 00000000..bc2e037c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/CgnsGrid.h @@ -0,0 +1,71 @@ +#pragma once +#include +#include + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03b/Field.cpp b/example/1d-heat-equation/ftcs/cpp/03b/Field.cpp new file mode 100644 index 00000000..63ab0c34 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/Field.cpp @@ -0,0 +1 @@ +#include "Field.h" diff --git a/example/1d-heat-equation/ftcs/cpp/03b/Field.h b/example/1d-heat-equation/ftcs/cpp/03b/Field.h new file mode 100644 index 00000000..9c6cfb64 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/Field.h @@ -0,0 +1,163 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ) + { + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + int ist = 0; + int ied = ni - 1; + + // 0(bc) 1(ist) 2 3 ... ni + + //int ist = 0 + 1; + //int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + //un[ ist - 1 ] = 0.0; + //un[ ied + 1 ] = 0.0; + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + } + + void Solve( Grid * grid ) + { + Boundary( grid ); + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + this->update( un, u ); + } + + void Boundary( Grid * grid ) + { + this->InterfaceBoundary( grid ); + this->PhysicalBoundary( grid ); + } + + void PhysicalBoundary( Grid * grid ) + { + BC * bc = Global::bcs[ grid->zoneIndex ]; + + int nBFace = bc->bctypes.size(); + for ( int i = 0; i < nBFace; ++ i ) + { + int bctype = bc->bctypes[ i ]; + int faceId = bc->faceids[ i ]; + if ( bctype == BCInflow ) + { + u[ faceId ] = 0.0; + } + else if ( bctype == BCOutflow ) + { + u[ faceId ] = 0.0; + } + } + } + + void InterfaceBoundary( Grid * grid ) + { + InterFaceZone * interfacezone = Global::interfacezones[ grid->zoneIndex ]; + int nInterfaces = interfacezone->left_u.size(); + for ( int i = 0; i < nInterfaces; ++ i ) + { + double ul = interfacezone->left_u[ i ]; + double ur = interfacezone->right_u[ i ]; + double um = 0.5 * ( ul + ur ); + + int faceId = interfacezone->face_ids[ i ]; + + u[ faceId ] = um; + int kkk = 1; + } + } + + void PostProcess( Grid * grid ) + { + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + } + + void AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) + { + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03b/README.txt b/example/1d-heat-equation/ftcs/cpp/03b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/03b/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/03b/Solver.cpp new file mode 100644 index 00000000..77b572c6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/Solver.cpp @@ -0,0 +1,57 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03b/Solver.h b/example/1d-heat-equation/ftcs/cpp/03b/Solver.h new file mode 100644 index 00000000..aef7a8a3 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/Solver.h @@ -0,0 +1,153 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); +void DumpErrorDetails( std::vector & u_error ); +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + +class Solver +{ +public: + void Run() + { + this->ReadGrid(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); + } + + void ReadGrid() + { + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + int kkk = 1; + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point(grid->x[i]) ); + } + int kkk = 1; + } + } + + void InitFields() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = new Field(); + Global::fields.push_back( field ); + field->Init( grid ); + } + } + + void SolveMultiZones() + { + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceValue(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Solve( grid ); + } + } + } + + void ExchangeInterfaceValue() + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } + } + + void PostProcess() + { + int nZones = Global::grids.size(); + std::vector u_e; + std::vector un; + std::vector x; + + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->AddData( ptfactory, grid, x, u_e, un ); + } + + std::cout << " x.size() = " << x.size() << "\n"; + + this->PostProcess( x, u_e, un ); + } + + void PostProcess( std::vector &x, std::vector &u_e, std::vector &un ) + { + int ni = x.size(); + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); + } + + void PrintField( std::vector &f ) + { + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; + } +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03b/global.cpp b/example/1d-heat-equation/ftcs/cpp/03b/global.cpp new file mode 100644 index 00000000..15b26cf9 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/global.cpp @@ -0,0 +1,16 @@ +#include "global.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03b/global.h b/example/1d-heat-equation/ftcs/cpp/03b/global.h new file mode 100644 index 00000000..1d39b9b5 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/global.h @@ -0,0 +1,216 @@ +#pragma once +#include +#include +#include +#include + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point(const value_type &x) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + + +class Field; +class BC; +class InterFaceZone; + +class Zone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/03b/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/03b/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/03b/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/03b/main.cpp b/example/1d-heat-equation/ftcs/cpp/03b/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/03b/plot.py b/example/1d-heat-equation/ftcs/cpp/03b/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/03b/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/03b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03b/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/03c/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/03c/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/03c/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/03c/CgnsGrid.cpp new file mode 100644 index 00000000..9afd6e1b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/CgnsGrid.cpp @@ -0,0 +1,383 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03c/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/03c/CgnsGrid.h new file mode 100644 index 00000000..bc2e037c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/CgnsGrid.h @@ -0,0 +1,71 @@ +#pragma once +#include +#include + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03c/Field.cpp b/example/1d-heat-equation/ftcs/cpp/03c/Field.cpp new file mode 100644 index 00000000..157f362c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/Field.cpp @@ -0,0 +1,145 @@ +#include "Field.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + int ist = 0; + int ied = ni - 1; + + // 0(bc) 1(ist) 2 3 ... ni + + //int ist = 0 + 1; + //int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + //un[ ist - 1 ] = 0.0; + //un[ ied + 1 ] = 0.0; + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; +} + +void Field::Solve( Grid * grid ) +{ + Boundary( grid ); + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + this->update( un, u ); +} + +void Field::Boundary( Grid * grid ) +{ + this->InterfaceBoundary( grid ); + this->PhysicalBoundary( grid ); +} + +void Field::PhysicalBoundary( Grid * grid ) +{ + BC * bc = Global::bcs[ grid->zoneIndex ]; + + int nBFace = bc->bctypes.size(); + for ( int i = 0; i < nBFace; ++ i ) + { + int bctype = bc->bctypes[ i ]; + int faceId = bc->faceids[ i ]; + if ( bctype == BCInflow ) + { + u[ faceId ] = 0.0; + } + else if ( bctype == BCOutflow ) + { + u[ faceId ] = 0.0; + } + } +} + +void Field::InterfaceBoundary( Grid * grid ) +{ + InterFaceZone * interfacezone = Global::interfacezones[ grid->zoneIndex ]; + int nInterfaces = interfacezone->left_u.size(); + for ( int i = 0; i < nInterfaces; ++ i ) + { + double ul = interfacezone->left_u[ i ]; + double ur = interfacezone->right_u[ i ]; + double um = 0.5 * ( ul + ur ); + + int faceId = interfacezone->face_ids[ i ]; + + u[ faceId ] = um; + int kkk = 1; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) +{ + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } +} + +void Field::update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03c/Field.h b/example/1d-heat-equation/ftcs/cpp/03c/Field.h new file mode 100644 index 00000000..d406764c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/Field.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + void Solve( Grid * grid ); + + void Boundary( Grid * grid ); + void PhysicalBoundary( Grid * grid ); + void InterfaceBoundary( Grid * grid ); + + void PostProcess( Grid * grid ); + void AddData( PointFactory & ptfactory, Grid * grid, std::vector & global_x, std::vector & global_ue, std::vector & global_un ); + void update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03c/README.txt b/example/1d-heat-equation/ftcs/cpp/03c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/03c/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/03c/Solver.cpp new file mode 100644 index 00000000..1ad96c33 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/Solver.cpp @@ -0,0 +1,196 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + int kkk = 1; + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = new Field(); + Global::fields.push_back( field ); + field->Init( grid ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceValue(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Solve( grid ); + } + } +} + +void Solver::ExchangeInterfaceValue() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } +} + +void Solver::PostProcess() +{ + int nZones = Global::grids.size(); + std::vector u_e; + std::vector un; + std::vector x; + + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->AddData( ptfactory, grid, x, u_e, un ); + } + + std::cout << " x.size() = " << x.size() << "\n"; + + this->PostProcess( x, u_e, un ); +} + +void Solver::PostProcess( std::vector &x, std::vector &u_e, std::vector &un ) +{ + int ni = x.size(); + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03c/Solver.h b/example/1d-heat-equation/ftcs/cpp/03c/Solver.h new file mode 100644 index 00000000..aa90b98a --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/Solver.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); +void DumpErrorDetails( std::vector & u_error ); +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void SolveMultiZones(); + void ExchangeInterfaceValue(); + void PostProcess(); + void PostProcess( std::vector & x, std::vector & u_e, std::vector & un ); + void PrintField( std::vector & f ); + +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03c/global.cpp b/example/1d-heat-equation/ftcs/cpp/03c/global.cpp new file mode 100644 index 00000000..15b26cf9 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/global.cpp @@ -0,0 +1,16 @@ +#include "global.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03c/global.h b/example/1d-heat-equation/ftcs/cpp/03c/global.h new file mode 100644 index 00000000..db2d1ad1 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/global.h @@ -0,0 +1,216 @@ +#pragma once +#include +#include +#include +#include + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + + +class Field; +class BC; +class InterFaceZone; + +class Zone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/03c/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/03c/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/03c/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/03c/main.cpp b/example/1d-heat-equation/ftcs/cpp/03c/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/03c/plot.py b/example/1d-heat-equation/ftcs/cpp/03c/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/03c/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/03c/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03c/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/03d/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/03d/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/03d/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/03d/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03d/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/03d/CgnsGrid.h new file mode 100644 index 00000000..42633021 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/CgnsGrid.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03d/Field.cpp b/example/1d-heat-equation/ftcs/cpp/03d/Field.cpp new file mode 100644 index 00000000..b4fe1304 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/Field.cpp @@ -0,0 +1,220 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Grid * grid ) +{ + Boundary( grid ); + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + this->Update( un, u ); +} + +void Field::Boundary( Grid * grid ) +{ + this->InterfaceBoundary( grid ); + this->PhysicalBoundary( grid ); +} + +void Field::PhysicalBoundary( Grid * grid ) +{ + BC * bc = Global::bcs[ grid->zoneIndex ]; + + int nBFace = bc->bctypes.size(); + for ( int i = 0; i < nBFace; ++ i ) + { + int bctype = bc->bctypes[ i ]; + int faceId = bc->faceids[ i ]; + if ( bctype == BCInflow ) + { + u[ faceId ] = 0.0; + } + else if ( bctype == BCOutflow ) + { + u[ faceId ] = 0.0; + } + } +} + +void Field::InterfaceBoundary( Grid * grid ) +{ + InterFaceZone * interfacezone = Global::interfacezones[ grid->zoneIndex ]; + int nInterfaces = interfacezone->left_u.size(); + for ( int i = 0; i < nInterfaces; ++ i ) + { + double ul = interfacezone->left_u[ i ]; + double ur = interfacezone->right_u[ i ]; + double um = 0.5 * ( ul + ur ); + + int faceId = interfacezone->face_ids[ i ]; + + u[ faceId ] = um; + int kkk = 1; + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + + this->PhysicalBoundary( zone ); + + this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int id = i + 1; + if ( i == 1 ) + { + id = i - 1; + } + this->u[ id ] = 0.0; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int id = i + 1; + if ( i == 1 ) + { + id = i - 1; + } + this->u[ id ] = 0.0; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) +{ + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03d/Field.h b/example/1d-heat-equation/ftcs/cpp/03d/Field.h new file mode 100644 index 00000000..83a79354 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/Field.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + void Solve( Grid * grid ); + + void Solve( Zone * zone ); + + void Boundary( Grid * grid ); + void PhysicalBoundary( Grid * grid ); + void InterfaceBoundary( Grid * grid ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void AddData( PointFactory & ptfactory, Grid * grid, std::vector & global_x, std::vector & global_ue, std::vector & global_un ); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03d/README.txt b/example/1d-heat-equation/ftcs/cpp/03d/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/03d/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/03d/Solver.cpp new file mode 100644 index 00000000..c0373f45 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/Solver.cpp @@ -0,0 +1,451 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); + //this->PostProcessNewVersion(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceValue(); + ExchangeInterfaceField(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->Solve( grid ); + //field->Solve( zone ); + } + } +} + +void Solver::InitInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + interface->uList.resize( nInterFaces ); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceValue() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } +} + +void Solver::PostProcess() +{ + int nZones = Global::grids.size(); + std::vector u_e; + std::vector un; + std::vector x; + + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->AddData( ptfactory, grid, x, u_e, un ); + } + + std::cout << " x.size() = " << x.size() << "\n"; + + this->PostProcess( x, u_e, un ); +} + +void Solver::PostProcessNewVersion() +{ + Post post; + post.Process(); + //int nZones = Global::grids.size(); + //std::vector u_e; + //std::vector un; + //std::vector x; + + //PointFactory ptfactory; + //for ( int iZone = 0; iZone < nZones; ++ iZone ) + //{ + // Grid * grid = Global::grids[ iZone ]; + // Field * field = Global::fields[ iZone ]; + // field->AddData( ptfactory, grid, x, u_e, un ); + //} + + //std::cout << " x.size() = " << x.size() << "\n"; + + //this->PostProcess( x, u_e, un ); +} + +void Solver::PostProcess( std::vector &x, std::vector &u_e, std::vector &un ) +{ + int ni = x.size(); + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03d/Solver.h b/example/1d-heat-equation/ftcs/cpp/03d/Solver.h new file mode 100644 index 00000000..552774bb --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/Solver.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); +void DumpErrorDetails( std::vector & u_error ); +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); + void ExchangeInterfaceValue(); +public: + void InitInterfaceField(); + void ExchangeInterfaceField(); + void PostProcess(); + void PostProcess( std::vector & x, std::vector & u_e, std::vector & un ); + void PrintField( std::vector & f ); +public: + void PostProcessNewVersion(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03d/global.cpp b/example/1d-heat-equation/ftcs/cpp/03d/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03d/global.h b/example/1d-heat-equation/ftcs/cpp/03d/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/03d/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/03d/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/03d/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/03d/main.cpp b/example/1d-heat-equation/ftcs/cpp/03d/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/03d/plot.py b/example/1d-heat-equation/ftcs/cpp/03d/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/03d/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/03d/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03d/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/03e/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/03e/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/03e/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/03e/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03e/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/03e/CgnsGrid.h new file mode 100644 index 00000000..42633021 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/CgnsGrid.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03e/Field.cpp b/example/1d-heat-equation/ftcs/cpp/03e/Field.cpp new file mode 100644 index 00000000..a5a2d44e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/Field.cpp @@ -0,0 +1,171 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + + this->PhysicalBoundary( zone ); + + this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) +{ + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03e/Field.h b/example/1d-heat-equation/ftcs/cpp/03e/Field.h new file mode 100644 index 00000000..fd3c5004 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/Field.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void AddData( PointFactory & ptfactory, Grid * grid, std::vector & global_x, std::vector & global_ue, std::vector & global_un ); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03e/README.txt b/example/1d-heat-equation/ftcs/cpp/03e/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/03e/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/03e/Solver.cpp new file mode 100644 index 00000000..a9cc0764 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/Solver.cpp @@ -0,0 +1,386 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcessNewVersion(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceField(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->Solve( zone ); + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceValue() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } +} + +void Solver::PostProcessNewVersion() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + ::DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + ::DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03e/Solver.h b/example/1d-heat-equation/ftcs/cpp/03e/Solver.h new file mode 100644 index 00000000..b9a668a0 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/Solver.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); +void DumpErrorDetails( std::vector & u_error ); +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); + void ExchangeInterfaceValue(); +public: + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcessNewVersion(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03e/global.cpp b/example/1d-heat-equation/ftcs/cpp/03e/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03e/global.h b/example/1d-heat-equation/ftcs/cpp/03e/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/03e/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/03e/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/03e/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/03e/main.cpp b/example/1d-heat-equation/ftcs/cpp/03e/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/03e/plot.py b/example/1d-heat-equation/ftcs/cpp/03e/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/03e/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/03e/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03e/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/03f/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/03f/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/03f/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/03f/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03f/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/03f/CgnsGrid.h new file mode 100644 index 00000000..42633021 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/CgnsGrid.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03f/Field.cpp b/example/1d-heat-equation/ftcs/cpp/03f/Field.cpp new file mode 100644 index 00000000..a5a2d44e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/Field.cpp @@ -0,0 +1,171 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + + this->PhysicalBoundary( zone ); + + this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) +{ + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03f/Field.h b/example/1d-heat-equation/ftcs/cpp/03f/Field.h new file mode 100644 index 00000000..fd3c5004 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/Field.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void AddData( PointFactory & ptfactory, Grid * grid, std::vector & global_x, std::vector & global_ue, std::vector & global_un ); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03f/README.txt b/example/1d-heat-equation/ftcs/cpp/03f/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/03f/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/03f/Solver.cpp new file mode 100644 index 00000000..1c1c4d10 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/Solver.cpp @@ -0,0 +1,383 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcessNewVersion(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceField(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->Solve( zone ); + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceValue() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } +} + +void Solver::PostProcessNewVersion() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03f/Solver.h b/example/1d-heat-equation/ftcs/cpp/03f/Solver.h new file mode 100644 index 00000000..a9cf6554 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); + void ExchangeInterfaceValue(); +public: + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcessNewVersion(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03f/global.cpp b/example/1d-heat-equation/ftcs/cpp/03f/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03f/global.h b/example/1d-heat-equation/ftcs/cpp/03f/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/03f/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/03f/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/03f/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/03f/main.cpp b/example/1d-heat-equation/ftcs/cpp/03f/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/03f/plot.py b/example/1d-heat-equation/ftcs/cpp/03f/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/03f/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/03f/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03f/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/03g/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/03g/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/03g/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/03g/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03g/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/03g/CgnsGrid.h new file mode 100644 index 00000000..42633021 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/CgnsGrid.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03g/Field.cpp b/example/1d-heat-equation/ftcs/cpp/03g/Field.cpp new file mode 100644 index 00000000..af25e484 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/Field.cpp @@ -0,0 +1,173 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = static_cast( t / dt ) + 1; + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + + this->PhysicalBoundary( zone ); + + this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) +{ + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03g/Field.h b/example/1d-heat-equation/ftcs/cpp/03g/Field.h new file mode 100644 index 00000000..fd3c5004 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/Field.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void AddData( PointFactory & ptfactory, Grid * grid, std::vector & global_x, std::vector & global_ue, std::vector & global_un ); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03g/README.txt b/example/1d-heat-equation/ftcs/cpp/03g/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/03g/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/03g/Solver.cpp new file mode 100644 index 00000000..af074429 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/Solver.cpp @@ -0,0 +1,381 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceField(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->Solve( zone ); + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceValue() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03g/Solver.h b/example/1d-heat-equation/ftcs/cpp/03g/Solver.h new file mode 100644 index 00000000..3ce472a7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); + void ExchangeInterfaceValue(); +public: + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03g/global.cpp b/example/1d-heat-equation/ftcs/cpp/03g/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/03g/global.h b/example/1d-heat-equation/ftcs/cpp/03g/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/03g/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/03g/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/03g/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/03g/main.cpp b/example/1d-heat-equation/ftcs/cpp/03g/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/03g/plot.py b/example/1d-heat-equation/ftcs/cpp/03g/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/03g/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/03g/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/03g/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01/CgnsGrid.h new file mode 100644 index 00000000..42633021 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/CgnsGrid.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01/Field.cpp new file mode 100644 index 00000000..c48fc14e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/Field.cpp @@ -0,0 +1,156 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + //this->nt = 1; + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + //u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * xm ); //theory solution + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + + this->PhysicalBoundary( zone ); + + this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01/Field.h new file mode 100644 index 00000000..0645e99d --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01/Solver.cpp new file mode 100644 index 00000000..aa9703cc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/Solver.cpp @@ -0,0 +1,372 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceField(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->Solve( zone ); + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); + //this->DumpCsvFile( csvname, x, u_e, un, u, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + //std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &u, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un u uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + //std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], u[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01/Solver.h new file mode 100644 index 00000000..a0d8ad69 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/Solver.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & u, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/01/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/01/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/01/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/CgnsGrid.h new file mode 100644 index 00000000..42633021 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/CgnsGrid.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Field.cpp new file mode 100644 index 00000000..ef15f943 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Field.cpp @@ -0,0 +1,226 @@ +#include "Field.h" +#include "CgnsGrid.h" + +int Para::nt = -1; +double Para::dx = 0; +double Para::dt = 0; +double Para::t = 0; +double Para::alpha = 0; +double Para::beta = 0; + +void Para::Init() +{ + Para::dx = 0.025; + Para::dt = dx / 10.0; + Para::t = 1.0; + Para::nt = std::round( t / dt ); +} + +void GenGrid( std::vector & gx ); +void GenGrid( std::vector & gx ) +{ + const int ni = 81; + gx.resize( ni ); + + double x_l = -1.0; + double x_r = 1.0; + + double dx = ( x_r - x_l ) / ( ni - 1 ); + + for ( int i = 0; i < ni; ++ i ) + { + gx[ i ] = x_l + i * dx; + } +} + +void Field::ModifyGrid( Grid * grid ) +{ + std::vector globalx; + GenGrid( globalx ); + + this->ni = grid->x.size(); + + int ishift = 0; + + if ( grid->zoneIndex == 1 ) + { + ishift = ni - 1; + } + + for ( int i = 0; i < ni; ++ i ) + { + grid->x[ i ] = globalx[ i + ishift ]; + } +} + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + this->ModifyGrid( grid ); + + std::vector & x = grid->x; + //this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + //this->dt = dx / 10.0; + //this->t = 1.0; + //this->nt = std::round( t / dt ); + + this->dx = Para::dx; + this->dt = Para::dt; + this->t = Para::t; + this->nt = Para::nt; + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << std::setprecision( 25 ) << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + if ( std::abs( xm - 0.2 ) < 1.0e-5 ) + { + double term1 = xm; + double term2 = std::sin( std::numbers::pi * xm ); + double term3 = std::exp( -total_time ); + double term4 = term2 * term3; + std::cout << "this->dx = " << std::setprecision( 25 ) << this->dx << "\n"; + std::cout << "this->dt = " << std::setprecision( 25 ) << this->dt << "\n"; + std::cout << "total_time = " << std::setprecision( 25 ) << total_time << "\n"; + std::cout << "term1 = " << std::setprecision( 25 ) << term1 << "\n"; + std::cout << "term2 = " << std::setprecision( 25 ) << term2 << "\n"; + std::cout << "term3 = " << std::setprecision( 25 ) << term3 << "\n"; + std::cout << "term4 = " << std::setprecision( 25 ) << term4 << "\n"; + } + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + + this->PhysicalBoundary( zone ); + + this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Field.h new file mode 100644 index 00000000..45c9da82 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Field.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Para +{ +public: + static int nt; + static double dx, dt, t; + static double alpha, beta; +public: + static void Init(); +}; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void ModifyGrid( Grid * grid ); + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Solver.cpp new file mode 100644 index 00000000..8c62b5f7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Solver.cpp @@ -0,0 +1,373 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + Para::Init(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceField(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->Solve( zone ); + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); + //this->DumpCsvFile( csvname, x, u_e, un, u, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + //std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &u, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un u uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + //std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], u[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Solver.h new file mode 100644 index 00000000..a0d8ad69 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/Solver.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & u, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01a/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01a/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Field.cpp new file mode 100644 index 00000000..a4ccd6d0 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Field.cpp @@ -0,0 +1,256 @@ +#include "Field.h" +#include "CgnsGrid.h" + +int Para::nt = -1; +double Para::dx = 0; +double Para::dt = 0; +double Para::t = 0; +double Para::alpha = 0; +double Para::beta = 0; + +void Para::Init() +{ + Para::dx = 0.025; + Para::dt = dx / 10.0; + Para::t = 1.0; + Para::nt = std::round( t / dt ); + //Para::nt = 2; + //Para::nt = 1; + +} + +void GenGrid( std::vector & gx ); +void GenGrid( std::vector & gx ) +{ + const int ni = 81; + gx.resize( ni ); + + double x_l = -1.0; + double x_r = 1.0; + + double dx = ( x_r - x_l ) / ( ni - 1 ); + + for ( int i = 0; i < ni; ++ i ) + { + gx[ i ] = x_l + i * dx; + } +} + +void Field::ModifyGrid( Grid * grid ) +{ + std::vector globalx; + GenGrid( globalx ); + + this->ni = grid->x.size(); + + int ishift = 0; + + if ( grid->zoneIndex == 1 ) + { + ishift = ni - 1; + } + + for ( int i = 0; i < ni; ++ i ) + { + grid->x[ i ] = globalx[ i + ishift ]; + } +} + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + this->ModifyGrid( grid ); + + std::vector & x = grid->x; + //this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + //this->dt = dx / 10.0; + //this->t = 1.0; + //this->nt = std::round( t / dt ); + + this->dx = Para::dx; + this->dt = Para::dt; + this->t = Para::t; + this->nt = Para::nt; + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << std::setprecision( 25 ) << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 25 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 25 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + if ( std::abs( xm - 0.2 ) < 1.0e-5 ) + { + double term1 = xm; + double term2 = std::sin( std::numbers::pi * xm ); + double term3 = std::exp( -total_time ); + double term4 = term2 * term3; + std::cout << "this->dx = " << std::setprecision( 25 ) << this->dx << "\n"; + std::cout << "this->dt = " << std::setprecision( 25 ) << this->dt << "\n"; + std::cout << "total_time = " << std::setprecision( 25 ) << total_time << "\n"; + std::cout << "term1 = " << std::setprecision( 25 ) << term1 << "\n"; + std::cout << "term2 = " << std::setprecision( 25 ) << term2 << "\n"; + std::cout << "term3 = " << std::setprecision( 25 ) << term3 << "\n"; + std::cout << "term4 = " << std::setprecision( 25 ) << term4 << "\n"; + } + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double term1 = un[ i - 1 ]; + double term2 = un[ i ]; + double term3 = un[ i + 1 ]; + double term4 = term1 -2.0 * term2 + term3; + double term5 = beta * term4; + double term6 = term2 + term5; + if ( ( zone->zoneIndex == 0 && i== ied ) || + ( zone->zoneIndex == 1 && i== ist ) ) + { + std::cout << "zone->zoneIndex = " << zone->zoneIndex << "\n"; + std::cout << "term1 = " << std::setprecision( 25 ) << term1 << "\n"; + std::cout << "term2 = " << std::setprecision( 25 ) << term2 << "\n"; + std::cout << "term3 = " << std::setprecision( 25 ) << term3 << "\n"; + std::cout << "term4 = " << std::setprecision( 25 ) << term4 << "\n"; + std::cout << "term5 = " << std::setprecision( 25 ) << term5 << "\n"; + std::cout << "term6 = " << std::setprecision( 25 ) << term6 << "\n"; + } + + //u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + u[ i ] = term6; + } + + //this->PhysicalBoundary( zone ); + + //this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Field.h new file mode 100644 index 00000000..756154a3 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Field.h @@ -0,0 +1,48 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Para +{ +public: + static int nt; + static double dx, dt, t; + static double alpha, beta; +public: + static void Init(); +}; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void ModifyGrid( Grid * grid ); + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Solver.cpp new file mode 100644 index 00000000..d5d054b4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Solver.cpp @@ -0,0 +1,398 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + Para::Init(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + //std::string csvname = "field_final.csv"; + //this->DumpCsvFile( csvname, x, u_e, un, u_error ); + //std::string csvname_test = "field_final_test.csv"; + //this->DumpCsvFile( csvname_test, x, u_e, un, u, u_error ); + + std::string csvname = "field_final0.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); + std::string csvname_test = "field_final_test0.csv"; + this->DumpCsvFile( csvname_test, x, u_e, un, u, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + //std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &u, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un u uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + //std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], u[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Solver.h new file mode 100644 index 00000000..6bcc4ef4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/Solver.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & u, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01b/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01b/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/CgnsGrid.cpp new file mode 100644 index 00000000..ef59dfcd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/CgnsGrid.cpp @@ -0,0 +1,551 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Field.cpp new file mode 100644 index 00000000..d7cbd0d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Field.cpp @@ -0,0 +1,170 @@ +#include "Field.h" +#include "CgnsGrid.h" + +int Para::nt = -1; +double Para::dx = 0; +double Para::dt = 0; +double Para::t = 0; +double Para::alpha = 0; +double Para::beta = 0; + +void Para::Init() +{ + Para::dx = 0.025; + Para::dt = dx / 10.0; + Para::t = 1.0; + Para::nt = std::round( t / dt ); +} + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + //this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + //this->dt = dx / 10.0; + //this->t = 1.0; + //this->nt = std::round( t / dt ); + + this->dx = Para::dx; + this->dt = Para::dt; + this->t = Para::t; + this->nt = Para::nt; + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << std::setprecision( 25 ) << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 25 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 25 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Field.h new file mode 100644 index 00000000..21441ef6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Field.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Para +{ +public: + static int nt; + static double dx, dt, t; + static double alpha, beta; +public: + static void Init(); +}; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Solver.cpp new file mode 100644 index 00000000..0b659536 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Solver.cpp @@ -0,0 +1,353 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + Para::Init(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Solver.h new file mode 100644 index 00000000..6bcc4ef4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/Solver.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & u, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01c/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01c/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Field.cpp new file mode 100644 index 00000000..d7cbd0d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Field.cpp @@ -0,0 +1,170 @@ +#include "Field.h" +#include "CgnsGrid.h" + +int Para::nt = -1; +double Para::dx = 0; +double Para::dt = 0; +double Para::t = 0; +double Para::alpha = 0; +double Para::beta = 0; + +void Para::Init() +{ + Para::dx = 0.025; + Para::dt = dx / 10.0; + Para::t = 1.0; + Para::nt = std::round( t / dt ); +} + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + //this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + //this->dt = dx / 10.0; + //this->t = 1.0; + //this->nt = std::round( t / dt ); + + this->dx = Para::dx; + this->dt = Para::dt; + this->t = Para::t; + this->nt = Para::nt; + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << std::setprecision( 25 ) << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 25 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 25 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Field.h new file mode 100644 index 00000000..21441ef6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Field.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Para +{ +public: + static int nt; + static double dx, dt, t; + static double alpha, beta; +public: + static void Init(); +}; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Solver.cpp new file mode 100644 index 00000000..0b659536 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Solver.cpp @@ -0,0 +1,353 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + Para::Init(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Solver.h new file mode 100644 index 00000000..6bcc4ef4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/Solver.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & u, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/global.cpp new file mode 100644 index 00000000..4e1c2242 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/global.cpp @@ -0,0 +1,52 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/global.h new file mode 100644 index 00000000..95708796 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/global.h @@ -0,0 +1,91 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijk_ghosts; + std::vector ijk_donors; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01d/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01d/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Field.cpp new file mode 100644 index 00000000..16b28ddc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Field.cpp @@ -0,0 +1,141 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Solver.cpp new file mode 100644 index 00000000..b275e660 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Solver.cpp @@ -0,0 +1,352 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d2blocksv3.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Solver.h new file mode 100644 index 00000000..c50415cf --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/global.cpp new file mode 100644 index 00000000..4e1c2242 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/global.cpp @@ -0,0 +1,52 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/global.h new file mode 100644 index 00000000..95708796 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/global.h @@ -0,0 +1,91 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijk_ghosts; + std::vector ijk_donors; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/heat1d2blocksv3.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/heat1d2blocksv3.cgns new file mode 100644 index 00000000..1621b92e Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/heat1d2blocksv3.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/01e/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/01e/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Field.cpp new file mode 100644 index 00000000..16b28ddc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Field.cpp @@ -0,0 +1,141 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Solver.cpp new file mode 100644 index 00000000..7fc4555e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Solver.cpp @@ -0,0 +1,352 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Solver.h new file mode 100644 index 00000000..c50415cf --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/global.cpp new file mode 100644 index 00000000..4e1c2242 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/global.cpp @@ -0,0 +1,52 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/global.h new file mode 100644 index 00000000..ce3710b6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/global.h @@ -0,0 +1,90 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijk_ghosts; + std::vector ijk_donors; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/main.cpp @@ -0,0 +1,8 @@ +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/4blocks/01/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Field.cpp new file mode 100644 index 00000000..16b28ddc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Field.cpp @@ -0,0 +1,141 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Solver.cpp new file mode 100644 index 00000000..f1d05b41 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Solver.cpp @@ -0,0 +1,352 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d8blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Solver.h new file mode 100644 index 00000000..c50415cf --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/global.cpp new file mode 100644 index 00000000..4e1c2242 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/global.cpp @@ -0,0 +1,52 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/global.h new file mode 100644 index 00000000..ce3710b6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/global.h @@ -0,0 +1,90 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijk_ghosts; + std::vector ijk_donors; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/heat1d8blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/heat1d8blocksv1.cgns new file mode 100644 index 00000000..4dc174d4 Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/heat1d8blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/main.cpp @@ -0,0 +1,8 @@ +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/8blocks/01/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Field.cpp new file mode 100644 index 00000000..16b28ddc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Field.cpp @@ -0,0 +1,141 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Solver.cpp new file mode 100644 index 00000000..4728853b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Solver.cpp @@ -0,0 +1,388 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceFieldOldVersion() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + double donor_value = donor_field->u[ i_donor_cell ]; + interface->data_recv[ iFace ] = donor_value; + } + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Solver.h new file mode 100644 index 00000000..8ef894af --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/Solver.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void ExchangeInterfaceFieldOldVersion(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/global.cpp new file mode 100644 index 00000000..4e1c2242 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/global.cpp @@ -0,0 +1,52 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/global.h new file mode 100644 index 00000000..f6783581 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/global.h @@ -0,0 +1,92 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/main.cpp @@ -0,0 +1,8 @@ +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Field.cpp new file mode 100644 index 00000000..16b28ddc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Field.cpp @@ -0,0 +1,141 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Solver.cpp new file mode 100644 index 00000000..6c6672bc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Solver.cpp @@ -0,0 +1,442 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceFieldOldVersion() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceFieldOldVersion1() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + double donor_value = donor_field->u[ i_donor_cell ]; + interface->data_recv[ iFace ] = donor_value; + } + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + //for ( int iZone = 0; iZone < nZones; ++ iZone ) + //{ + // Field * field = Global::fields[ iZone ]; + + // Interface * interface = Global::interfaces[ iZone ]; + // int nInterFaces = interface->zoneList.size(); + // int index_dim = 1; + // for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + // { + // int donor_zoneid = interface->zoneList[ iFace ]; + // int ijkpos = index_dim * iFace; + // int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + // Field * donor_field = Global::fields[ donor_zoneid ]; + // double donor_value = donor_field->u[ i_donor_cell ]; + // interface->data_recv[ iFace ] = donor_value; + // //interface->data_send[ iFace ] = donor_value; + // } + //} + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + double donor_value = donor_field->u[ i_donor_cell ]; + interface->data_recv[ iFace ] = donor_value; + } + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Solver.h new file mode 100644 index 00000000..e739edf7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/Solver.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void ExchangeInterfaceFieldOldVersion(); + void ExchangeInterfaceFieldOldVersion1(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/global.cpp new file mode 100644 index 00000000..93e76c83 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/global.cpp @@ -0,0 +1,127 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + //std::map::iterator iter; + //iter = Global::faceMap.find( face ); + //if ( iter == Global::faceMap.end() ) + //{ + // int faceid = Global::faceMap.size(); + // Global::faceMap.insert( std::make_pair( face, faceid ) ); + //} + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/global.h new file mode 100644 index 00000000..d5d20440 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/global.h @@ -0,0 +1,120 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + //bool operator < ( const FacePair & rhs ) const; +}; + +class Transform; + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector faceidList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/main.cpp @@ -0,0 +1,8 @@ +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01a/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Field.cpp new file mode 100644 index 00000000..16b28ddc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Field.cpp @@ -0,0 +1,141 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Solver.cpp new file mode 100644 index 00000000..6c6672bc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Solver.cpp @@ -0,0 +1,442 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceFieldOldVersion() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceFieldOldVersion1() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + double donor_value = donor_field->u[ i_donor_cell ]; + interface->data_recv[ iFace ] = donor_value; + } + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + //for ( int iZone = 0; iZone < nZones; ++ iZone ) + //{ + // Field * field = Global::fields[ iZone ]; + + // Interface * interface = Global::interfaces[ iZone ]; + // int nInterFaces = interface->zoneList.size(); + // int index_dim = 1; + // for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + // { + // int donor_zoneid = interface->zoneList[ iFace ]; + // int ijkpos = index_dim * iFace; + // int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + // Field * donor_field = Global::fields[ donor_zoneid ]; + // double donor_value = donor_field->u[ i_donor_cell ]; + // interface->data_recv[ iFace ] = donor_value; + // //interface->data_send[ iFace ] = donor_value; + // } + //} + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + double donor_value = donor_field->u[ i_donor_cell ]; + interface->data_recv[ iFace ] = donor_value; + } + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Solver.h new file mode 100644 index 00000000..e739edf7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/Solver.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void ExchangeInterfaceFieldOldVersion(); + void ExchangeInterfaceFieldOldVersion1(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/global.cpp new file mode 100644 index 00000000..67e1bb0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/global.cpp @@ -0,0 +1,160 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + Global::InsertFacePairMap( facePair ); + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +void Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/global.h new file mode 100644 index 00000000..8f54626e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/global.h @@ -0,0 +1,122 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector faceidList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static void InsertFacePairMap( const FacePair & facePair ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/main.cpp @@ -0,0 +1,8 @@ +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01b/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Field.cpp new file mode 100644 index 00000000..16b28ddc --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Field.cpp @@ -0,0 +1,141 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Solver.cpp new file mode 100644 index 00000000..bcba6407 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Solver.cpp @@ -0,0 +1,654 @@ +#include "Solver.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + Global::donor_zone_sets.resize( nZones ); + Global::donor_zones.resize( nZones ); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + //std::cout << "donorzone = " << donorzone << " donorfaces = "; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + std::cout << "zone = " << iZone << " donorzone = "; + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::cout << donorzone; + if( iNei != ndonor_zones - 1 ) + { + std::cout << ","; + } + } + std::cout << "\n"; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::cout << "donorzone = " << donorzone << " donorfaces = "; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + int ndonorfaces = neighbor_donorface.size(); + for ( int idonorface = 0; idonorface < ndonorfaces; ++ idonorface ) + { + std::cout << neighbor_donorface[ idonorface ]; + if( idonorface != ndonorfaces - 1 ) + { + std::cout << ","; + } + } + std::cout << "\n"; + } + std::cout << "\n"; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::cout << "zone_to_send = " << zone_to_send << " donorfaces_for_send = "; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + int nFace = donorfaces.size(); + for ( int iFace = 0; iFace < nFace; ++ iFace ) + { + std::cout << donorfaces[ iFace ]; + if( iFace != nFace - 1 ) + { + std::cout << ","; + } + } + std::cout << "\n"; + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + Global::ReSendGeomTest( iZone, zone_to_send, donorfaces ); + } + int kkk = 1; + } + + std::cout << "\n"; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + int tmp_recv_donor_zone = interface->tmp_recv_donor_zones[ iNei ]; + + std::cout << "donorzone = " << donorzone << " tmp_recv_donor_zone = " << tmp_recv_donor_zone << "\n"; + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::cout << "neighbor_donorfaces\n"; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + std::cout << neighbor_donorfaces[ i ] << " "; + } + std::cout << "\n"; + std::vector & tmp_recv_donorfaces = interface->tmp_recv_donorfaces[ iNei ]; + std::cout << "tmp_recv_donorfaces\n"; + for ( int i = 0; i < tmp_recv_donorfaces.size(); ++ i ) + { + std::cout << tmp_recv_donorfaces[ i ] << " "; + } + std::cout << "\n"; + } + } + + int kkk = 1; +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceFieldOldVersion() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceFieldOldVersion1() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + double donor_value = donor_field->u[ i_donor_cell ]; + interface->data_recv[ iFace ] = donor_value; + } + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + //zone0: + //donor zone2 donorfaces(0) + //zone0->send_geom(zone=2,facelist(0)) : + // zone2->recv_geom(zone=0,facelist(0)); + // zone2->get_value(facelist(0),valuelist(200)); + // zone2->send_value(zone=0,valuelist(200)); + //zone0->recv_value(zone=2,valuelist(200)); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::cout << "zone = " << iZone << "\n"; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::cout << "donorzone = " << donorzone << "\n"; + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int global_faceid = neighbor_donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int mylocal = sub_local_faceids[ i ]; + std::cout << " global_faceid = " << global_faceid << " local_faceid = " << local_faceid + << " mylocal = " << mylocal << "\n"; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + double donor_value = donor_field->u[ i_donor_cell ]; + interface->data_recv[ iFace ] = donor_value; + } + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Solver.h new file mode 100644 index 00000000..e739edf7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/Solver.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void ExchangeInterfaceFieldOldVersion(); + void ExchangeInterfaceFieldOldVersion1(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/global.cpp new file mode 100644 index 00000000..236b90d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/global.cpp @@ -0,0 +1,185 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); +} + +void Global::ReSendGeomTest( int zone, int zone_to_send, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ zone_to_send ]; + interface->tmp_recv_donor_zones.push_back( zone ); + interface->tmp_recv_donorfaces.push_back( donorfaces ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/global.h new file mode 100644 index 00000000..ed0a20ff --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/global.h @@ -0,0 +1,142 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector tmp_recv_donor_zones; + std::vector> tmp_recv_donorfaces; +public: + std::vector recv_donor_zones; + std::vector> recv_donor_fields; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); + static void ReSendGeomTest( int zone, int zone_to_send, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/main.cpp @@ -0,0 +1,8 @@ +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01c/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Solver.cpp new file mode 100644 index 00000000..f97e4454 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Solver.cpp @@ -0,0 +1,648 @@ +#include "Solver.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + Global::donor_zone_sets.resize( nZones ); + Global::donor_zones.resize( nZones ); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + //std::cout << "donorzone = " << donorzone << " donorfaces = "; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + std::cout << "zone = " << iZone << " donorzone = "; + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::cout << donorzone; + if( iNei != ndonor_zones - 1 ) + { + std::cout << ","; + } + } + std::cout << "\n"; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::cout << "donorzone = " << donorzone << " donorfaces = "; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + int ndonorfaces = neighbor_donorface.size(); + for ( int idonorface = 0; idonorface < ndonorfaces; ++ idonorface ) + { + std::cout << neighbor_donorface[ idonorface ]; + if( idonorface != ndonorfaces - 1 ) + { + std::cout << ","; + } + } + std::cout << "\n"; + } + std::cout << "\n"; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::cout << "zone_to_send = " << zone_to_send << " donorfaces_for_send = "; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + int nFace = donorfaces.size(); + for ( int iFace = 0; iFace < nFace; ++ iFace ) + { + std::cout << donorfaces[ iFace ]; + if( iFace != nFace - 1 ) + { + std::cout << ","; + } + } + std::cout << "\n"; + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + Global::ReSendGeomTest( iZone, zone_to_send, donorfaces ); + } + int kkk = 1; + } + + std::cout << "\n"; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + int tmp_recv_donor_zone = interface->tmp_recv_donor_zones[ iNei ]; + + std::cout << "donorzone = " << donorzone << " tmp_recv_donor_zone = " << tmp_recv_donor_zone << "\n"; + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::cout << "neighbor_donorfaces\n"; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + std::cout << neighbor_donorfaces[ i ] << " "; + } + std::cout << "\n"; + std::vector & tmp_recv_donorfaces = interface->tmp_recv_donorfaces[ iNei ]; + std::cout << "tmp_recv_donorfaces\n"; + for ( int i = 0; i < tmp_recv_donorfaces.size(); ++ i ) + { + std::cout << tmp_recv_donorfaces[ i ] << " "; + } + std::cout << "\n"; + } + } + + int kkk = 1; +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + //zone0: + //donor zone2 donorfaces(0) + //zone0->send_geom(zone=2,facelist(0)) : + // zone2->recv_geom(zone=0,facelist(0)); + // zone2->get_value(facelist(0),valuelist(200)); + // zone2->send_value(zone=0,valuelist(200)); + //zone0->recv_value(zone=2,valuelist(200)); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::cout << "donorzone = " << donorzone << "\n"; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + //for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + //{ + // int donor_zoneid = interface->zoneList[ iFace ]; + // int ijkpos = index_dim * iFace; + // int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + // Field * donor_field = Global::fields[ donor_zoneid ]; + // double donor_value = donor_field->u[ i_donor_cell ]; + // interface->data_recv[ iFace ] = donor_value; + //} + + int index_dim = 1; + std::vector rrr( nInterFaces ); + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + double donor_value = donor_field->u[ i_donor_cell ]; + rrr[ iFace ] = donor_value; + } + + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Solver.h new file mode 100644 index 00000000..c50415cf --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/global.cpp new file mode 100644 index 00000000..27ae141f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/global.cpp @@ -0,0 +1,206 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_local_donors.push_back( i_local_donor_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_local_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::ReSendGeomTest( int zone, int zone_to_send, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ zone_to_send ]; + interface->tmp_recv_donor_zones.push_back( zone ); + interface->tmp_recv_donorfaces.push_back( donorfaces ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/global.h new file mode 100644 index 00000000..7de16ba6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/global.h @@ -0,0 +1,145 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector ijk_local_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; + std::vector tmp_recv_donor_zones; + std::vector> tmp_recv_donorfaces; +public: + std::vector recv_donor_zones; + std::vector> recv_donor_fields; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); + static void ReSendGeomTest( int zone, int zone_to_send, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/main.cpp @@ -0,0 +1,8 @@ +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01d/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Solver.cpp new file mode 100644 index 00000000..292d9b24 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Solver.cpp @@ -0,0 +1,614 @@ +#include "Solver.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + Global::donor_zone_sets.resize( nZones ); + Global::donor_zones.resize( nZones ); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + //std::cout << "donorzone = " << donorzone << " donorfaces = "; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + std::cout << "zone = " << iZone << " donorzone = "; + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::cout << donorzone; + if( iNei != ndonor_zones - 1 ) + { + std::cout << ","; + } + } + std::cout << "\n"; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::cout << "donorzone = " << donorzone << " donorfaces = "; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + int ndonorfaces = neighbor_donorface.size(); + for ( int idonorface = 0; idonorface < ndonorfaces; ++ idonorface ) + { + std::cout << neighbor_donorface[ idonorface ]; + if( idonorface != ndonorfaces - 1 ) + { + std::cout << ","; + } + } + std::cout << "\n"; + } + std::cout << "\n"; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::cout << "zone_to_send = " << zone_to_send << " donorfaces_for_send = "; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + int nFace = donorfaces.size(); + for ( int iFace = 0; iFace < nFace; ++ iFace ) + { + std::cout << donorfaces[ iFace ]; + if( iFace != nFace - 1 ) + { + std::cout << ","; + } + } + std::cout << "\n"; + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + Global::ReSendGeomTest( iZone, zone_to_send, donorfaces ); + } + int kkk = 1; + } + + std::cout << "\n"; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + int tmp_recv_donor_zone = interface->tmp_recv_donor_zones[ iNei ]; + + std::cout << "donorzone = " << donorzone << " tmp_recv_donor_zone = " << tmp_recv_donor_zone << "\n"; + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::cout << "neighbor_donorfaces\n"; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + std::cout << neighbor_donorfaces[ i ] << " "; + } + std::cout << "\n"; + std::vector & tmp_recv_donorfaces = interface->tmp_recv_donorfaces[ iNei ]; + std::cout << "tmp_recv_donorfaces\n"; + for ( int i = 0; i < tmp_recv_donorfaces.size(); ++ i ) + { + std::cout << tmp_recv_donorfaces[ i ] << " "; + } + std::cout << "\n"; + } + } + + int kkk = 1; +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Solver.h new file mode 100644 index 00000000..c50415cf --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/global.cpp new file mode 100644 index 00000000..aef4b670 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/global.cpp @@ -0,0 +1,197 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::ReSendGeomTest( int zone, int zone_to_send, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ zone_to_send ]; + interface->tmp_recv_donor_zones.push_back( zone ); + interface->tmp_recv_donorfaces.push_back( donorfaces ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/global.h new file mode 100644 index 00000000..6736167a --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/global.h @@ -0,0 +1,144 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; + std::vector tmp_recv_donor_zones; + std::vector> tmp_recv_donorfaces; +public: + std::vector recv_donor_zones; + std::vector> recv_donor_fields; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); + static void ReSendGeomTest( int zone, int zone_to_send, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/main.cpp @@ -0,0 +1,8 @@ +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01e/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/CMakeLists.txt new file mode 100644 index 00000000..d395576a --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/CMakeLists.txt @@ -0,0 +1,94 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Solver.cpp new file mode 100644 index 00000000..97d3fdc6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Solver.cpp @@ -0,0 +1,503 @@ +#include "Solver.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + Global::donor_zone_sets.resize( nZones ); + Global::donor_zones.resize( nZones ); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + //std::cout << "donorzone = " << donorzone << " donorfaces = "; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + } + + std::cout << "\n"; + + int kkk = 1; +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + //std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Solver.h new file mode 100644 index 00000000..c50415cf --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/global.cpp new file mode 100644 index 00000000..d96bf9d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/global.cpp @@ -0,0 +1,191 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/global.h new file mode 100644 index 00000000..ce8eef97 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/global.h @@ -0,0 +1,138 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/main.cpp new file mode 100644 index 00000000..f96606d0 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/main.cpp @@ -0,0 +1,23 @@ +#include "mpi.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + int rank, size, len; + char version[MPI_MAX_LIBRARY_VERSION_STRING]; + + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + MPI_Get_library_version(version, &len); + std::cout << "Hello, world! I am " << rank << " of " << size + << "(" << version << ", " << len << ")" << std::endl; + if ( rank == 0 ) + { + Solver solver; + solver.Run(); + } + + MPI_Finalize(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/01f/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/CMakeLists.txt new file mode 100644 index 00000000..038616a3 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/CMakeLists.txt @@ -0,0 +1,97 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/CgnsGrid.cpp new file mode 100644 index 00000000..14e34203 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/CgnsGrid.cpp @@ -0,0 +1,523 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Parallel.cpp new file mode 100644 index 00000000..c4a40b66 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Parallel.cpp @@ -0,0 +1,31 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Parallel.h new file mode 100644 index 00000000..3e6f50e2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Parallel.h @@ -0,0 +1,17 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Solver.cpp new file mode 100644 index 00000000..23056f12 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Solver.cpp @@ -0,0 +1,518 @@ +#include "Solver.h" +#include "Parallel.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + if ( Parallel::pid == Parallel::serverid ) + { + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); + } +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + Global::donor_zone_sets.resize( nZones ); + Global::donor_zones.resize( nZones ); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + //std::cout << "donorzone = " << donorzone << " donorfaces = "; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + } + + std::cout << "\n"; + + int kkk = 1; +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + //std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Solver.h new file mode 100644 index 00000000..d01d3d9c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/Solver.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/global.cpp new file mode 100644 index 00000000..d96bf9d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/global.cpp @@ -0,0 +1,191 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/global.h new file mode 100644 index 00000000..ce8eef97 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/global.h @@ -0,0 +1,138 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/CMakeLists.txt new file mode 100644 index 00000000..038616a3 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/CMakeLists.txt @@ -0,0 +1,97 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/CgnsGrid.cpp new file mode 100644 index 00000000..5cec92ac --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/CgnsGrid.cpp @@ -0,0 +1,673 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + MPI_Bcast( &icelldim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &iphysdim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + MPI_Bcast( &nzones, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + MPI_Bcast( &index_dim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + MPI_Bcast( zonename, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( isize.data(), index_dim * 3, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::pid == Parallel::serverid ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + //MPI_Bcast( &index_dim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize( index_dim * 3 ); + char zonename[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + MPI_Bcast( zonename, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( isize.data(), index_dim * 3, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + return; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + MPI_Bcast( &zoneType, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + MPI_Bcast( &ncoords, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + MPI_Bcast( coordname, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &dataType, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + if ( Parallel::pid == Parallel::serverid ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + } + + double * pcoor = (double *)coor->coord.data(); + + MPI_Bcast( pcoor, nNodes, MPI_DOUBLE, Parallel::serverid, MPI_COMM_WORLD ); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + MPI_Bcast( &nbocos, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::pid == Parallel::serverid ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + MPI_Bcast( &location, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + if ( Parallel::pid == Parallel::serverid ) + { + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + MPI_Bcast( boconame, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &bocotype, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &ptset_type, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &normalDataType, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &npnts, 1, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &normalListSize, 1, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &ndataset, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( normalIndex.data(), index_dim, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + + if ( Parallel::pid == Parallel::serverid ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + MPI_Bcast( pnts.data(), npnts * index_dim, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( normalList.data(), nNodes * iphysdim * sizeof( double ), MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + MPI_Bcast( &n1to1, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + if ( Parallel::pid == Parallel::serverid ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + MPI_Bcast( connectname, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( donorname, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( range.data(), npnts * index_dim, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( donor_range.data(), npnts * index_dim, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Parallel.cpp new file mode 100644 index 00000000..c4a40b66 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Parallel.cpp @@ -0,0 +1,31 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Parallel.h new file mode 100644 index 00000000..3e6f50e2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Parallel.h @@ -0,0 +1,17 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Solver.cpp new file mode 100644 index 00000000..20d6fc61 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Solver.cpp @@ -0,0 +1,519 @@ +#include "Solver.h" +#include "Parallel.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + //if ( Parallel::pid == Parallel::serverid ) + //{ + // this->ReadGrid(); + // this->InitTopo(); + // this->InitFields(); + // this->SolveMultiZones(); + // this->PostProcess(); + //} +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + //ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + Global::donor_zone_sets.resize( nZones ); + Global::donor_zones.resize( nZones ); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + //std::cout << "donorzone = " << donorzone << " donorfaces = "; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + } + + std::cout << "\n"; + + int kkk = 1; +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + //std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Solver.h new file mode 100644 index 00000000..d01d3d9c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/Solver.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/global.cpp new file mode 100644 index 00000000..d96bf9d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/global.cpp @@ -0,0 +1,191 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/global.h new file mode 100644 index 00000000..ce8eef97 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/global.h @@ -0,0 +1,138 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02a/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/CMakeLists.txt new file mode 100644 index 00000000..038616a3 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/CMakeLists.txt @@ -0,0 +1,97 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/CgnsGrid.cpp new file mode 100644 index 00000000..8341e8d4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/CgnsGrid.cpp @@ -0,0 +1,687 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + MPI_Bcast( &icelldim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &iphysdim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + MPI_Bcast( &nzones, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + MPI_Bcast( &index_dim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + MPI_Bcast( zonename, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( isize.data(), index_dim * 3, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::pid == Parallel::serverid ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + MPI_Bcast( &icelldim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &iphysdim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nzones( fileId, baseId, &nzones ); + } + MPI_Bcast( &nzones, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + MPI_Bcast( &index_dim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + MPI_Bcast( zonename, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( isize.data(), index_dim * 3, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + MPI_Bcast( &zoneType, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + MPI_Bcast( &ncoords, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + MPI_Bcast( coordname, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &dataType, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + if ( Parallel::pid == Parallel::serverid ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + } + + double * pcoor = (double *)coor->coord.data(); + + MPI_Bcast( pcoor, nNodes, MPI_DOUBLE, Parallel::serverid, MPI_COMM_WORLD ); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + MPI_Bcast( &nbocos, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::pid == Parallel::serverid ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + MPI_Bcast( &location, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + if ( Parallel::pid == Parallel::serverid ) + { + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + MPI_Bcast( boconame, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &bocotype, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &ptset_type, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &normalDataType, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &npnts, 1, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &normalListSize, 1, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &ndataset, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( normalIndex.data(), index_dim, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + + if ( Parallel::pid == Parallel::serverid ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + MPI_Bcast( pnts.data(), npnts * index_dim, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( normalList.data(), nNodes * iphysdim * sizeof( double ), MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + MPI_Bcast( &n1to1, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + if ( Parallel::pid == Parallel::serverid ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + MPI_Bcast( connectname, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( donorname, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( range.data(), npnts * index_dim, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( donor_range.data(), npnts * index_dim, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Parallel.cpp new file mode 100644 index 00000000..c4a40b66 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Parallel.cpp @@ -0,0 +1,31 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Parallel.h new file mode 100644 index 00000000..3e6f50e2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Parallel.h @@ -0,0 +1,17 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Solver.cpp new file mode 100644 index 00000000..be1a9053 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Solver.cpp @@ -0,0 +1,518 @@ +#include "Solver.h" +#include "Parallel.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + //if ( Parallel::pid == Parallel::serverid ) + //{ + // this->ReadGrid(); + // this->InitTopo(); + // this->InitFields(); + // this->SolveMultiZones(); + // this->PostProcess(); + //} +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + Global::donor_zone_sets.resize( nZones ); + Global::donor_zones.resize( nZones ); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + } + + std::cout << "\n"; + + int kkk = 1; +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + //std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Solver.h new file mode 100644 index 00000000..d01d3d9c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/Solver.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/global.cpp new file mode 100644 index 00000000..d96bf9d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/global.cpp @@ -0,0 +1,191 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/global.h new file mode 100644 index 00000000..ce8eef97 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/global.h @@ -0,0 +1,138 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02b/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/CgnsGrid.cpp new file mode 100644 index 00000000..de8b8efa --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/CgnsGrid.cpp @@ -0,0 +1,733 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + MPI_Bcast( &icelldim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &iphysdim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + MPI_Bcast( &nzones, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + + if ( Parallel::nProc == 1 ) + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = 0; + } + } + else + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = iZone; + } + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + MPI_Bcast( &index_dim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + MPI_Bcast( zonename, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( isize.data(), index_dim * 3, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::pid == Parallel::serverid ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + MPI_Bcast( &icelldim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &iphysdim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nzones( fileId, baseId, &nzones ); + } + MPI_Bcast( &nzones, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + //MPI_Bcast( &index_dim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + } + return; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + //MPI_Bcast( &index_dim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize( index_dim * 3 ); + char zonename[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + MPI_Bcast( zonename, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( isize.data(), index_dim * 3, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + return; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + MPI_Bcast( &zoneType, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + MPI_Bcast( &ncoords, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + MPI_Bcast( coordname, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &dataType, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + if ( Parallel::pid == Parallel::serverid ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + } + + double * pcoor = (double *)coor->coord.data(); + + MPI_Bcast( pcoor, nNodes, MPI_DOUBLE, Parallel::serverid, MPI_COMM_WORLD ); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + MPI_Bcast( &nbocos, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::pid == Parallel::serverid ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + MPI_Bcast( &location, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + if ( Parallel::pid == Parallel::serverid ) + { + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + MPI_Bcast( boconame, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &bocotype, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &ptset_type, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &normalDataType, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &npnts, 1, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &normalListSize, 1, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &ndataset, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( normalIndex.data(), index_dim, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + + if ( Parallel::pid == Parallel::serverid ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + MPI_Bcast( pnts.data(), npnts * index_dim, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( normalList.data(), nNodes * iphysdim * sizeof( double ), MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + MPI_Bcast( &n1to1, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + if ( Parallel::pid == Parallel::serverid ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + MPI_Bcast( connectname, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( donorname, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( range.data(), npnts * index_dim, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( donor_range.data(), npnts * index_dim, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Parallel.cpp new file mode 100644 index 00000000..fa42ac8d --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Parallel.cpp @@ -0,0 +1,49 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Parallel.h new file mode 100644 index 00000000..34ff06a6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Parallel.h @@ -0,0 +1,46 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + logFile << " send_pid = " << send_pid << "\n"; + logFile << " recv_pid = " << recv_pid << "\n"; + logFile << " Parallel::pid = " << Parallel::pid << "\n"; + + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + logFile << " buffer_size = " << buffer_size << "\n"; + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Solver.cpp new file mode 100644 index 00000000..a2d6783e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Solver.cpp @@ -0,0 +1,516 @@ +#include "Solver.h" +#include "Parallel.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + //if ( Parallel::pid == Parallel::serverid ) + //{ + // this->ReadGrid(); + // this->InitTopo(); + // this->InitFields(); + // this->SolveMultiZones(); + // this->PostProcess(); + //} +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + Global::donor_zone_sets.resize( nZones ); + Global::donor_zones.resize( nZones ); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + } + + std::cout << "\n"; +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + //std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Solver.h new file mode 100644 index 00000000..d01d3d9c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/Solver.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/ZoneState.cpp new file mode 100644 index 00000000..528305fe --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/ZoneState.cpp @@ -0,0 +1,15 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/ZoneState.h new file mode 100644 index 00000000..8d1863b7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/ZoneState.h @@ -0,0 +1,13 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/global.cpp new file mode 100644 index 00000000..d96bf9d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/global.cpp @@ -0,0 +1,191 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/global.h new file mode 100644 index 00000000..ce8eef97 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/global.h @@ -0,0 +1,138 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02c/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/CgnsGrid.cpp new file mode 100644 index 00000000..c9f72fa3 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/CgnsGrid.cpp @@ -0,0 +1,859 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + MPI_Bcast( &icelldim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &iphysdim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + MPI_Bcast( &nzones, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + + if ( Parallel::nProc == 1 ) + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = 0; + } + } + else + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = iZone; + } + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + MPI_Bcast( &index_dim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + MPI_Bcast( zonename, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( isize.data(), index_dim * 3, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::pid == Parallel::serverid ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + MPI_Bcast( &icelldim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &iphysdim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_nzones( fileId, baseId, &nzones ); + } + MPI_Bcast( &nzones, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::pid == Parallel::serverid ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + //std::vector isize( index_dim * 3 ); + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::pid == Parallel::serverid ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + //MPI_Bcast( zonename, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + //MPI_Bcast( isize.data(), index_dim * 3, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::pid == Parallel::serverid ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + //ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + //zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Parallel.h new file mode 100644 index 00000000..f42746a7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Parallel.h @@ -0,0 +1,48 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + logFile << " send_pid = " << send_pid << "\n"; + logFile << " recv_pid = " << recv_pid << "\n"; + logFile << " Parallel::pid = " << Parallel::pid << "\n"; + + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + logFile << "nElement = " << nElement << " buffer_size = " << buffer_size << "\n"; + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Solver.cpp new file mode 100644 index 00000000..a2d6783e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Solver.cpp @@ -0,0 +1,516 @@ +#include "Solver.h" +#include "Parallel.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + //if ( Parallel::pid == Parallel::serverid ) + //{ + // this->ReadGrid(); + // this->InitTopo(); + // this->InitFields(); + // this->SolveMultiZones(); + // this->PostProcess(); + //} +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + Global::donor_zone_sets.resize( nZones ); + Global::donor_zones.resize( nZones ); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + std::cout << "zone = " << iZone << "\n"; + + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + } + + std::cout << "\n"; +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + //std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Solver.h new file mode 100644 index 00000000..d01d3d9c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/Solver.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/ZoneState.cpp new file mode 100644 index 00000000..528305fe --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/ZoneState.cpp @@ -0,0 +1,15 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/ZoneState.h new file mode 100644 index 00000000..8d1863b7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/ZoneState.h @@ -0,0 +1,13 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/global.cpp new file mode 100644 index 00000000..d96bf9d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/global.cpp @@ -0,0 +1,191 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/global.h new file mode 100644 index 00000000..ce8eef97 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/global.h @@ -0,0 +1,138 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02d/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/CgnsGrid.cpp new file mode 100644 index 00000000..8e47482e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/CgnsGrid.cpp @@ -0,0 +1,854 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + MPI_Bcast( &icelldim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &iphysdim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + MPI_Bcast( &nzones, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + + if ( Parallel::nProc == 1 ) + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = 0; + } + } + else + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = iZone; + } + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + MPI_Bcast( &index_dim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + MPI_Bcast( zonename, 33, MPI_CHAR, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( isize.data(), index_dim * 3, MPI_LONG_LONG, Parallel::serverid, MPI_COMM_WORLD ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + MPI_Bcast( &icelldim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + MPI_Bcast( &iphysdim, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + MPI_Bcast( &nzones, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Parallel.h new file mode 100644 index 00000000..17045502 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Parallel.h @@ -0,0 +1,48 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + //logFile << " send_pid = " << send_pid << "\n"; + //logFile << " recv_pid = " << recv_pid << "\n"; + //logFile << " Parallel::pid = " << Parallel::pid << "\n"; + + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + //logFile << "nElement = " << nElement << " buffer_size = " << buffer_size << "\n"; + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Solver.cpp new file mode 100644 index 00000000..164d23c7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Solver.cpp @@ -0,0 +1,556 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + //if ( Parallel::pid == Parallel::serverid ) + //{ + this->SolveMultiZones(); + this->PostProcess(); + //} +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + //for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + //{ + // Zone * zone = Global::zones[ iZone ]; + + // Interface * interface = Global::interfaces[ iZone ]; + + // int nbc1to1s = zone->bc1to1s.size(); + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + // for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + // { + // ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + // int zoneid = bc1to1->zoneid; + // int donor_zoneid = bc1to1->donor_zoneid; + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + // Region region; + // region.SetRegion( bc1to1->pnts ); + + // Region donor_region; + // donor_region.SetRegion( bc1to1->donor_pnts ); + + // Transform transform; + // transform.begin1 = region.start; + // transform.begin2 = donor_region.start; + // transform.transform = bc1to1->transform; + // transform.Init(); + + // interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + // } + //} + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int index_dim = 1; + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + //std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Solver.h new file mode 100644 index 00000000..d01d3d9c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/Solver.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/ZoneState.cpp new file mode 100644 index 00000000..bdafab8c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/ZoneState.cpp @@ -0,0 +1,19 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/ZoneState.h new file mode 100644 index 00000000..35f9a1e8 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/ZoneState.h @@ -0,0 +1,20 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/global.cpp new file mode 100644 index 00000000..6d725629 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/global.cpp @@ -0,0 +1,241 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void Interface::CalcInterfaceOld( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/global.h new file mode 100644 index 00000000..1600c81e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/global.h @@ -0,0 +1,139 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterfaceOld( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02e/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/CgnsGrid.cpp new file mode 100644 index 00000000..4af275c7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/CgnsGrid.cpp @@ -0,0 +1,855 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + + if ( Parallel::nProc == 1 ) + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = 0; + } + } + else + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = iZone; + } + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Parallel.h new file mode 100644 index 00000000..2a9267d8 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Parallel.h @@ -0,0 +1,58 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + //logFile << " send_pid = " << send_pid << "\n"; + //logFile << " recv_pid = " << recv_pid << "\n"; + //logFile << " Parallel::pid = " << Parallel::pid << "\n"; + + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + //logFile << "nElement = " << nElement << " buffer_size = " << buffer_size << "\n"; + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Solver.cpp new file mode 100644 index 00000000..daa75a5e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Solver.cpp @@ -0,0 +1,573 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + ////if ( Parallel::pid == Parallel::serverid ) + ////{ + this->SolveMultiZones(); + this->PostProcess(); + ////} +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector &neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + Interface * interface = Global::interfaces[ donorzone ]; + interface->SendGeom( iZone, neighbor_donorface ); + + //Global::SendGeom( iZone, donorzone, neighbor_donorface ); + } + int kkk = 1; + } + return; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + int nZones = Global::zones.size(); + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::ExchangeInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } + int kkk = 1; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + + std::vector & neighbor_donor_zones = interface->neighbor_donor_zones; + int ndonor_zones = neighbor_donor_zones.size(); + + //std::vector> & recv_donor_fields = interface->recv_donor_fields; + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donorzone = neighbor_donor_zones[ iNei ]; + Interface * donor_interface = Global::interfaces[ donorzone ]; + int nSize = donor_interface->send_to_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int szone = donor_interface->send_to_zones[ i ]; + if ( szone == iZone ) + { + ipos = i; + break; + } + } + std::vector & donordata = donor_interface->donordata_for_send[ ipos ]; + + std::vector & neighbor_donorfaces = interface->neighbor_donorfaces[ iNei ]; + std::vector & sub_local_faceids = interface->sub_local_faceids[ iNei ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + interface->data_recv[ local_faceid ] = donor_value; + } + } + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Solver.h new file mode 100644 index 00000000..d01d3d9c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/Solver.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/ZoneState.cpp new file mode 100644 index 00000000..bdafab8c --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/ZoneState.cpp @@ -0,0 +1,19 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/ZoneState.h new file mode 100644 index 00000000..35f9a1e8 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/ZoneState.h @@ -0,0 +1,20 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/global.cpp new file mode 100644 index 00000000..991f0df0 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/global.cpp @@ -0,0 +1,291 @@ +#include "global.h" +#include "CgnsGrid.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void Interface::CalcInterfaceOld( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + Global::InsertFaceMap( face ); + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + Global::InsertFaceMap( face_donor ); + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int global_faceid = Global::InsertFacePairMap( facePair ); + this->global_faceids.push_back( global_faceid ); + + this->global_local_face_map.insert( std::make_pair( global_faceid, faceid ) ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + //Interface * interface = Global::interfaces[ donorzone ]; + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::SendGeom( int zone, int donorzone, std::vector & donorfaces ) +{ + Interface * interface = Global::interfaces[ donorzone ]; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/global.h new file mode 100644 index 00000000..fa3f5c92 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/global.h @@ -0,0 +1,148 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterfaceOld( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void SendGeom( int zone, int donorzone, std::vector & donorfaces ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02f/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/CgnsGrid.cpp new file mode 100644 index 00000000..566675e2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/CgnsGrid.cpp @@ -0,0 +1,858 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + + if ( Parallel::nProc == 1 ) + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = 0; + ZoneState::g2lzoneids[ iZone ] = iZone; + } + } + else + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = iZone; + ZoneState::g2lzoneids[ iZone ] = 0; + } + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Parallel.h new file mode 100644 index 00000000..2a9267d8 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Parallel.h @@ -0,0 +1,58 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + //logFile << " send_pid = " << send_pid << "\n"; + //logFile << " recv_pid = " << recv_pid << "\n"; + //logFile << " Parallel::pid = " << Parallel::pid << "\n"; + + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + //logFile << "nElement = " << nElement << " buffer_size = " << buffer_size << "\n"; + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Solver.cpp new file mode 100644 index 00000000..d07b92bf --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Solver.cpp @@ -0,0 +1,581 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + if ( Parallel::pid == Parallel::serverid ) + { + this->SolveMultiZones(); + this->PostProcess(); + } +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nsend = -1; + std::vector donordata; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Solver.h new file mode 100644 index 00000000..a7799d19 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/Solver.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/global.cpp new file mode 100644 index 00000000..8562907f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/global.cpp @@ -0,0 +1,301 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + //Interface * interface = Global::interfaces[ donorzone ]; + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02g/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/CgnsGrid.cpp new file mode 100644 index 00000000..4baf036f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/CgnsGrid.cpp @@ -0,0 +1,858 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + + if ( Parallel::nProc == 1 ) + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = 0; + ZoneState::g2lzoneids[ iZone ] = iZone; + } + } + else + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = iZone; + ZoneState::g2lzoneids[ iZone ] = 0; + } + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Field.cpp new file mode 100644 index 00000000..718f1385 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Field.cpp @@ -0,0 +1,143 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + this->nt = 1; + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Parallel.h @@ -0,0 +1,78 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag ); + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXSendChar( field, buffer_size, recv_pid, tag ); +} + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXRecvChar( field, buffer_size, send_pid, tag ); +} + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Solver.cpp new file mode 100644 index 00000000..8a355cc7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Solver.cpp @@ -0,0 +1,752 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = iZone; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UploadInterfaceField() +{ + logFile << "UploadInterfaceField\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + logFile << "ilocal zone = " << iZone << " global zone = " << LocalZone::global_zoneids[ iZone ] << "\n"; + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + logFile << "nsend_zones = " << nsend_zones << "\n"; + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + logFile << "iSend = " << iSend << " zone_to_send " << zone_to_send << "\n"; + logFile << "donorfaces = "; + for ( int i = 0; i < donorfaces.size(); ++ i ) + { + logFile << donorfaces[ i ] << " "; + } + logFile << "\n"; + logFile << "donordatas = "; + for ( int i = 0; i < donordatas.size(); ++ i ) + { + logFile << donordatas[ i ] << " "; + } + logFile << "\n"; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + logFile << "i = " << i << " nface " << nface << " i_donor_cell = " << i_donor_cell << "\n"; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + + logFile << "donordatas after = "; + for ( int i = 0; i < donordatas.size(); ++ i ) + { + logFile << donordatas[ i ] << " "; + } + logFile << "\n"; + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + logFile << "UpdateInterfaceField iZone = " << iZone << "\n"; + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + logFile << "iZone = " << iZone << " donor_zone = " << donor_zone << "\n"; + logFile << "send_pid = " << send_pid << " recv_pid = " << recv_pid << "\n"; + int nsend = -1; + std::vector donordata; + std::vector donorface; + if ( Parallel::pid != send_pid && Parallel::pid != recv_pid ) continue; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + donorface = interface->donorfaces_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + logFile << "nsend = " << nsend << "\n"; + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + donorface.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + HXSendRecvData( donorface.data(), donorface.size(), send_pid, recv_pid ); + logFile << "donordata = "; + for ( int i = 0; i < donordata.size(); ++ i ) + { + logFile << donordata[ i ] << " "; + } + logFile << "\n"; + logFile << "donorface = "; + for ( int i = 0; i < donorface.size(); ++ i ) + { + logFile << donorface[ i ] << " "; + } + logFile << "\n"; + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + logFile << "DownloadInterfaceField\n"; + logFile << "LocalZone::nZones = " << LocalZone::nZones << "\n"; + logFile << "iZone = " << iZone << " LocalZone::global_zoneids[iZone] = " << LocalZone::global_zoneids[ iZone ] << "\n"; + + logFile << "field->u[ 1 ] = " <u[ 1 ] << "\n"; + logFile << "field->u[ 21 ] = " <u[ 21 ] << "\n"; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + logFile << "donor_value = " << donor_value << "\n"; + logFile << "i_ghost_cell = " << i_ghost_cell << "\n"; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( !ZoneState::IsValid( iZone ) && !Parallel::IsServer() ) continue; + + double xmin = 0.0; + double xmax = 0.0; + + if ( ZoneState::IsValid( iZone ) ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Grid * grid = Global::grids[ local_zoneid ]; + int ni = grid->x.size(); + xmin = grid->x[ 0 ]; + xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + } + + HXSendRecvData( &xmin, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + HXSendRecvData( &xmax, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "xmin = " << xmin << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "xmax = " << xmax << "\n"; + } + + if ( Parallel::IsServer() ) + { + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + } + + if ( Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + for ( int i = 0; i < xmin_list.size(); ++ i ) + { + std::cout << "(" << xmin_list[ i ] << "," << xmax_list[ i ] << ") "; + } + std::cout << "\n"; + } + + if ( Parallel::IsServer() ) + { + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[ i ], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[ i ].second ); + } + } + + int kkk = 1; +} + +bool IsLastZone( int iZone ); +bool IsLastZone( int iZone ) +{ + return iZone == ZoneState::nZones - 1; +} + +void Post::AddVector( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + +void Post::GatherField() +{ + logFile << "Post::GatherField 1 \n"; + this->zoneids.resize( ZoneState::nZones ); + HXBcastData( this->zoneids.data(), this->zoneids.size(), Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Post::GatherField() this->zoneids = \n"; + for ( int i = 0; i < this->zoneids.size(); ++ i ) + { + std::cout << this->zoneids[ i ] << " "; + } + std::cout << "\n"; + + logFile << "Post::GatherField 2 \n"; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + logFile << "iZone = " << iZone << " zoneid = " << zoneid << "\n"; + logFile << "ZoneState::pids[ iZone ] = " << ZoneState::pids[ iZone ] << "\n"; + + if ( !ZoneState::IsValid( zoneid ) && !Parallel::IsServer() ) continue; + + int nSize = -1; + logFile << "nSize = " << nSize << "\n"; + std::vector local_x; + std::vector local_u_e; + std::vector local_un; + std::vector local_u; + + logFile << "Parallel::pid = " << Parallel::pid << " ZoneState::pids[ zoneid ] = " << ZoneState::pids[ zoneid ] << "\n"; + + if ( Parallel::pid == ZoneState::pids[ zoneid ] ) + { + int local_zoneid = ZoneState::g2lzoneids[ zoneid ]; + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + nSize = local_x.size(); + } + + logFile << "Parallel::pid = " << Parallel::pid << "\n"; + logFile << "ZoneState::pids[ zoneid ] = " << ZoneState::pids[ zoneid ] << "\n"; + logFile << "Parallel::serverid = " << Parallel::serverid << "\n"; + + int send_pid = ZoneState::pids[ zoneid ]; + logFile << "send_pid = " << send_pid << "\n"; + + HXSendRecvData( &nSize, 1, send_pid, Parallel::serverid ); + + logFile << "nSize = " << nSize << "\n"; + + if ( Parallel::IsServer() ) + { + local_x.resize( nSize ); + local_u_e.resize( nSize ); + local_un.resize( nSize ); + local_u.resize( nSize ); + } + + HXSendRecvData( local_x.data(), local_x.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u_e.data(), local_u_e.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_un.data(), local_un.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u.data(), local_u.size(), send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + this->AddVector( this->x, local_x ); + this->AddVector( this->u_e, local_u_e ); + this->AddVector( this->un, local_un ); + this->AddVector( this->u, local_u ); + } + } + + logFile << "Post::GatherField 3 \n"; +} + +void Post::DumpField() +{ + if ( !Parallel::IsServer() ) return; + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Solver.h new file mode 100644 index 00000000..9914c1d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); +public: + void AddVector( std::vector & a, std::vector & b ); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/global.cpp new file mode 100644 index 00000000..8562907f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/global.cpp @@ -0,0 +1,301 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + //Interface * interface = Global::interfaces[ donorzone ]; + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02h/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/CgnsGrid.cpp new file mode 100644 index 00000000..4baf036f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/CgnsGrid.cpp @@ -0,0 +1,858 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + + if ( Parallel::nProc == 1 ) + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = 0; + ZoneState::g2lzoneids[ iZone ] = iZone; + } + } + else + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = iZone; + ZoneState::g2lzoneids[ iZone ] = 0; + } + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Parallel.h @@ -0,0 +1,78 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag ); + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXSendChar( field, buffer_size, recv_pid, tag ); +} + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXRecvChar( field, buffer_size, send_pid, tag ); +} + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Solver.cpp new file mode 100644 index 00000000..e5f99802 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Solver.cpp @@ -0,0 +1,763 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + //logFile << "Solver::InitTopo()\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = global_zoneid; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + //logFile << "iZone = " << iZone << " LocalZone::global_zoneids[iZone] = " << LocalZone::global_zoneids[ iZone ] << "\n"; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + //std::cout << "Parallel::pid = " << Parallel::pid << " "; + //std::cout << "it = " << it << " nt = " << Global::nt << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UploadInterfaceField() +{ + //logFile << "UploadInterfaceField\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + //logFile << "ilocal zone = " << iZone << " global zone = " << LocalZone::global_zoneids[ iZone ] << "\n"; + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + //logFile << "nsend_zones = " << nsend_zones << "\n"; + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + //logFile << "iSend = " << iSend << " zone_to_send " << zone_to_send << "\n"; + //logFile << "donorfaces = "; + //for ( int i = 0; i < donorfaces.size(); ++ i ) + //{ + // logFile << donorfaces[ i ] << " "; + //} + //logFile << "\n"; + //logFile << "donordatas = "; + //for ( int i = 0; i < donordatas.size(); ++ i ) + //{ + // logFile << donordatas[ i ] << " "; + //} + //logFile << "\n"; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + //logFile << "i = " << i << " nface " << nface << " i_donor_cell = " << i_donor_cell << "\n"; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + + //logFile << "donordatas after = "; + //for ( int i = 0; i < donordatas.size(); ++ i ) + //{ + // logFile << donordatas[ i ] << " "; + //} + //logFile << "\n"; + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + //logFile << "UpdateInterfaceField iZone = " << iZone << "\n"; + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + //logFile << "iZone = " << iZone << " donor_zone = " << donor_zone << "\n"; + //logFile << "send_pid = " << send_pid << " recv_pid = " << recv_pid << "\n"; + int nsend = -1; + std::vector donordata; + //std::vector donorface; + if ( Parallel::pid != send_pid && Parallel::pid != recv_pid ) continue; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + //donorface = interface->donorfaces_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + //logFile << "nsend = " << nsend << "\n"; + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + //donorface.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + //HXSendRecvData( donorface.data(), donorface.size(), send_pid, recv_pid ); + //logFile << "donordata = "; + //for ( int i = 0; i < donordata.size(); ++ i ) + //{ + // logFile << donordata[ i ] << " "; + //} + //logFile << "\n"; + //logFile << "donorface = "; + //for ( int i = 0; i < donorface.size(); ++ i ) + //{ + // logFile << donorface[ i ] << " "; + //} + //logFile << "\n"; + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + //logFile << "DownloadInterfaceField\n"; + //logFile << "LocalZone::nZones = " << LocalZone::nZones << "\n"; + //logFile << "iZone = " << iZone << " LocalZone::global_zoneids[iZone] = " << LocalZone::global_zoneids[ iZone ] << "\n"; + + //logFile << "field->u[ 1 ] = " <u[ 1 ] << "\n"; + //logFile << "field->u[ 21 ] = " <u[ 21 ] << "\n"; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + //logFile << "donor_value = " << donor_value << "\n"; + //logFile << "i_ghost_cell = " << i_ghost_cell << "\n"; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( !ZoneState::IsValid( iZone ) && !Parallel::IsServer() ) continue; + + double xmin = 0.0; + double xmax = 0.0; + + if ( ZoneState::IsValid( iZone ) ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Grid * grid = Global::grids[ local_zoneid ]; + int ni = grid->x.size(); + xmin = grid->x[ 0 ]; + xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + } + + HXSendRecvData( &xmin, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + HXSendRecvData( &xmax, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "xmin = " << xmin << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "xmax = " << xmax << "\n"; + } + + if ( Parallel::IsServer() ) + { + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + } + + if ( Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + for ( int i = 0; i < xmin_list.size(); ++ i ) + { + std::cout << "(" << xmin_list[ i ] << "," << xmax_list[ i ] << ") "; + } + std::cout << "\n"; + } + + if ( Parallel::IsServer() ) + { + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[ i ], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[ i ].second ); + } + } + + int kkk = 1; +} + +bool IsLastZone( int iZone ); +bool IsLastZone( int iZone ) +{ + return iZone == ZoneState::nZones - 1; +} + +void Post::AddVector( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + +void Post::GatherField() +{ + logFile << "Post::GatherField 1 \n"; + this->zoneids.resize( ZoneState::nZones ); + HXBcastData( this->zoneids.data(), this->zoneids.size(), Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Post::GatherField() this->zoneids = \n"; + for ( int i = 0; i < this->zoneids.size(); ++ i ) + { + std::cout << this->zoneids[ i ] << " "; + } + std::cout << "\n"; + + logFile << "Post::GatherField 2 \n"; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + logFile << "iZone = " << iZone << " zoneid = " << zoneid << "\n"; + logFile << "ZoneState::pids[ iZone ] = " << ZoneState::pids[ iZone ] << "\n"; + + if ( !ZoneState::IsValid( zoneid ) && !Parallel::IsServer() ) continue; + + int nSize = -1; + logFile << "nSize = " << nSize << "\n"; + std::vector local_x; + std::vector local_u_e; + std::vector local_un; + std::vector local_u; + + logFile << "Parallel::pid = " << Parallel::pid << " ZoneState::pids[ zoneid ] = " << ZoneState::pids[ zoneid ] << "\n"; + + if ( Parallel::pid == ZoneState::pids[ zoneid ] ) + { + int local_zoneid = ZoneState::g2lzoneids[ zoneid ]; + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + nSize = local_x.size(); + } + + logFile << "Parallel::pid = " << Parallel::pid << "\n"; + logFile << "ZoneState::pids[ zoneid ] = " << ZoneState::pids[ zoneid ] << "\n"; + logFile << "Parallel::serverid = " << Parallel::serverid << "\n"; + + int send_pid = ZoneState::pids[ zoneid ]; + logFile << "send_pid = " << send_pid << "\n"; + + HXSendRecvData( &nSize, 1, send_pid, Parallel::serverid ); + + logFile << "nSize = " << nSize << "\n"; + + if ( Parallel::IsServer() ) + { + local_x.resize( nSize ); + local_u_e.resize( nSize ); + local_un.resize( nSize ); + local_u.resize( nSize ); + } + + HXSendRecvData( local_x.data(), local_x.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u_e.data(), local_u_e.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_un.data(), local_un.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u.data(), local_u.size(), send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + this->AddVector( this->x, local_x ); + this->AddVector( this->u_e, local_u_e ); + this->AddVector( this->un, local_un ); + this->AddVector( this->u, local_u ); + } + } + + logFile << "Post::GatherField 3 \n"; +} + +void Post::DumpField() +{ + //logFile << "Post::DumpField() \n"; + if ( !Parallel::IsServer() ) return; + int ni_total = this->x.size(); + //logFile << " DumpField x.size() = " << x.size() << "\n"; + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + //logFile << "DumpErrorDetails \n"; + + this->DumpErrorDetails( u_error ); + + //logFile << "DumpCsvFile \n"; + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); + //logFile << "DumpCsvFile End \n"; +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Solver.h new file mode 100644 index 00000000..9914c1d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); +public: + void AddVector( std::vector & a, std::vector & b ); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/global.cpp new file mode 100644 index 00000000..8562907f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/global.cpp @@ -0,0 +1,301 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + //Interface * interface = Global::interfaces[ donorzone ]; + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02i/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/CgnsGrid.cpp new file mode 100644 index 00000000..4baf036f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/CgnsGrid.cpp @@ -0,0 +1,858 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + + if ( Parallel::nProc == 1 ) + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = 0; + ZoneState::g2lzoneids[ iZone ] = iZone; + } + } + else + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = iZone; + ZoneState::g2lzoneids[ iZone ] = 0; + } + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Parallel.h @@ -0,0 +1,78 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag ); + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXSendChar( field, buffer_size, recv_pid, tag ); +} + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXRecvChar( field, buffer_size, send_pid, tag ); +} + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Solver.cpp new file mode 100644 index 00000000..25038559 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Solver.cpp @@ -0,0 +1,680 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d4blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = global_zoneid; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + //std::cout << "Parallel::pid = " << Parallel::pid << " "; + //std::cout << "it = " << it << " nt = " << Global::nt << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nsend = -1; + std::vector donordata; + if ( Parallel::pid != send_pid && Parallel::pid != recv_pid ) continue; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( !ZoneState::IsValid( iZone ) && !Parallel::IsServer() ) continue; + + double xmin = 0.0; + double xmax = 0.0; + + if ( ZoneState::IsValid( iZone ) ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Grid * grid = Global::grids[ local_zoneid ]; + int ni = grid->x.size(); + xmin = grid->x[ 0 ]; + xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + } + + HXSendRecvData( &xmin, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + HXSendRecvData( &xmax, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmin = " << xmin << "\n"; + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmax = " << xmax << "\n"; + //} + + if ( Parallel::IsServer() ) + { + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + } + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // for ( int i = 0; i < xmin_list.size(); ++ i ) + // { + // std::cout << "(" << xmin_list[ i ] << "," << xmax_list[ i ] << ") "; + // } + // std::cout << "\n"; + //} + + if ( Parallel::IsServer() ) + { + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[ i ], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[ i ].second ); + } + } + + int kkk = 1; +} + +bool IsLastZone( int iZone ); +bool IsLastZone( int iZone ) +{ + return iZone == ZoneState::nZones - 1; +} + +void Post::AddVector( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + +void Post::GatherField() +{ + this->zoneids.resize( ZoneState::nZones ); + HXBcastData( this->zoneids.data(), this->zoneids.size(), Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Post::GatherField() this->zoneids = \n"; + for ( int i = 0; i < this->zoneids.size(); ++ i ) + { + std::cout << this->zoneids[ i ] << " "; + } + std::cout << "\n"; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + + if ( !ZoneState::IsValid( zoneid ) && !Parallel::IsServer() ) continue; + + int nSize = -1; + std::vector local_x; + std::vector local_u_e; + std::vector local_un; + std::vector local_u; + + if ( Parallel::pid == ZoneState::pids[ zoneid ] ) + { + int local_zoneid = ZoneState::g2lzoneids[ zoneid ]; + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + nSize = local_x.size(); + } + + int send_pid = ZoneState::pids[ zoneid ]; + + HXSendRecvData( &nSize, 1, send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + local_x.resize( nSize ); + local_u_e.resize( nSize ); + local_un.resize( nSize ); + local_u.resize( nSize ); + } + + HXSendRecvData( local_x.data(), local_x.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u_e.data(), local_u_e.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_un.data(), local_un.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u.data(), local_u.size(), send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + this->AddVector( this->x, local_x ); + this->AddVector( this->u_e, local_u_e ); + this->AddVector( this->un, local_un ); + this->AddVector( this->u, local_u ); + } + } +} + +void Post::DumpField() +{ + if ( !Parallel::IsServer() ) return; + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Solver.h new file mode 100644 index 00000000..9914c1d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); +public: + void AddVector( std::vector & a, std::vector & b ); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/global.cpp @@ -0,0 +1,300 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/4blocks/02j/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/CgnsGrid.cpp new file mode 100644 index 00000000..4baf036f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/CgnsGrid.cpp @@ -0,0 +1,858 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + + if ( Parallel::nProc == 1 ) + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = 0; + ZoneState::g2lzoneids[ iZone ] = iZone; + } + } + else + { + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + ZoneState::pids[ iZone ] = iZone; + ZoneState::g2lzoneids[ iZone ] = 0; + } + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Parallel.h @@ -0,0 +1,78 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag ); + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXSendChar( field, buffer_size, recv_pid, tag ); +} + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXRecvChar( field, buffer_size, send_pid, tag ); +} + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/README.txt @@ -0,0 +1,3 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. + +PS D:\github\OneFLOW\example\1d-heat-equation\ftcs\cpp\multiblock\parallel\8blocks\01\build> mpiexec -n 8 .\Debug\testprj.exe diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Solver.cpp new file mode 100644 index 00000000..6035f616 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Solver.cpp @@ -0,0 +1,680 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d8blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = global_zoneid; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + //std::cout << "Parallel::pid = " << Parallel::pid << " "; + //std::cout << "it = " << it << " nt = " << Global::nt << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nsend = -1; + std::vector donordata; + if ( Parallel::pid != send_pid && Parallel::pid != recv_pid ) continue; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( !ZoneState::IsValid( iZone ) && !Parallel::IsServer() ) continue; + + double xmin = 0.0; + double xmax = 0.0; + + if ( ZoneState::IsValid( iZone ) ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Grid * grid = Global::grids[ local_zoneid ]; + int ni = grid->x.size(); + xmin = grid->x[ 0 ]; + xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + } + + HXSendRecvData( &xmin, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + HXSendRecvData( &xmax, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmin = " << xmin << "\n"; + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmax = " << xmax << "\n"; + //} + + if ( Parallel::IsServer() ) + { + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + } + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // for ( int i = 0; i < xmin_list.size(); ++ i ) + // { + // std::cout << "(" << xmin_list[ i ] << "," << xmax_list[ i ] << ") "; + // } + // std::cout << "\n"; + //} + + if ( Parallel::IsServer() ) + { + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[ i ], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[ i ].second ); + } + } + + int kkk = 1; +} + +bool IsLastZone( int iZone ); +bool IsLastZone( int iZone ) +{ + return iZone == ZoneState::nZones - 1; +} + +void Post::AddVector( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + +void Post::GatherField() +{ + this->zoneids.resize( ZoneState::nZones ); + HXBcastData( this->zoneids.data(), this->zoneids.size(), Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Post::GatherField() this->zoneids = \n"; + for ( int i = 0; i < this->zoneids.size(); ++ i ) + { + std::cout << this->zoneids[ i ] << " "; + } + std::cout << "\n"; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + + if ( !ZoneState::IsValid( zoneid ) && !Parallel::IsServer() ) continue; + + int nSize = -1; + std::vector local_x; + std::vector local_u_e; + std::vector local_un; + std::vector local_u; + + if ( Parallel::pid == ZoneState::pids[ zoneid ] ) + { + int local_zoneid = ZoneState::g2lzoneids[ zoneid ]; + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + nSize = local_x.size(); + } + + int send_pid = ZoneState::pids[ zoneid ]; + + HXSendRecvData( &nSize, 1, send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + local_x.resize( nSize ); + local_u_e.resize( nSize ); + local_un.resize( nSize ); + local_u.resize( nSize ); + } + + HXSendRecvData( local_x.data(), local_x.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u_e.data(), local_u_e.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_un.data(), local_un.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u.data(), local_u.size(), send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + this->AddVector( this->x, local_x ); + this->AddVector( this->u_e, local_u_e ); + this->AddVector( this->un, local_un ); + this->AddVector( this->u, local_u ); + } + } +} + +void Post::DumpField() +{ + if ( !Parallel::IsServer() ) return; + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Solver.h new file mode 100644 index 00000000..9914c1d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); +public: + void AddVector( std::vector & a, std::vector & b ); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/global.cpp @@ -0,0 +1,300 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/heat1d8blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/heat1d8blocksv1.cgns new file mode 100644 index 00000000..4dc174d4 Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/heat1d8blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package ( MPI ) + +message ( STATUS "MPI_FOUND=${MPI_FOUND}" ) +message ( STATUS "MPI_CXX_INCLUDE_DIRS=${MPI_CXX_INCLUDE_DIRS}" ) +message ( STATUS "MPI_LIBRARIES=${MPI_LIBRARIES}" ) +if ( MPI_FOUND ) + list ( APPEND PRJ_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS} ) + list ( APPEND PRJ_LIBRARIES ${MPI_LIBRARIES} ) +endif () + +#get_directory_property( my_import_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPORTED_TARGETS ) +#message( STATUS "my_import_targets=${my_import_targets}" ) + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +list ( APPEND PRJ_COMPILE_DEFINITIONS HX_PARALLEL ) + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Solver.h Solver.cpp + ZoneState.h ZoneState.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/CgnsGrid.cpp @@ -0,0 +1,850 @@ +#include "CgnsGrid.h" +#include "Parallel.h" +#include "cgnslib.h" +#include "global.h" +#include "ZoneState.h" +#include +#include + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + HXBcastData( &nbases, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + + HXBcastData( &nzones, 1, Parallel::serverid ); + + ZoneState::nZones = nzones; + ZoneState::pids.resize( nzones ); + ZoneState::g2lzoneids.resize( nzones ); + std::vector pcount( Parallel::nProc, 0 ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zone_pid = iZone % Parallel::nProc; + ZoneState::pids[ iZone ] = zone_pid; + ZoneState::g2lzoneids[ iZone ] = pcount[ zone_pid ]; + pcount[ zone_pid ] ++; + } + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << "\n"; + + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXBcastData( &index_dim, 1, Parallel::serverid ); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + HXBcastData( zonename, 33, Parallel::serverid ); + HXBcastData( isize.data(), isize.size(), Parallel::serverid); + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + + if ( Parallel::IsServer() ) + { + cg_close( fileId ); + } +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + if ( Parallel::IsServer() ) + { + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + } + + int nbases = -1; + if ( Parallel::IsServer() ) + { + cg_nbases( fileId, &nbases ); + } + MPI_Bcast( &nbases, 1, MPI_INT, Parallel::serverid, MPI_COMM_WORLD ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + if ( Parallel::IsServer() ) + { + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + } + + HXBcastData( &icelldim, 1, Parallel::serverid ); + HXBcastData( &iphysdim, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + + int nzones = -1; + if ( Parallel::IsServer() ) + { + cg_nzones( fileId, baseId, &nzones ); + } + HXBcastData( &nzones, 1, Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nzones = " << nzones << "\n"; + + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + if ( Parallel::IsServer() ) + { + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + } + HXSendRecvData( &index_dim, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "index_dim = " << index_dim << "\n"; + } + + std::vector isize; + char zonename[ 33 ]; + if ( Parallel::IsServer() ) + { + isize.resize( index_dim * 3 ); + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + isize.resize( index_dim * 3 ); + } + + HXSendRecvData( zonename, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( isize.data(), index_dim * 3, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zonename = " << zonename << "\n"; + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + } + + std::vector irmin; + std::vector irmax; + int nNodes = 1; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + irmin.resize( index_dim ); + irmax.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nNodes = " << nNodes << "\n"; + } + + ZoneType_t zoneType; + if ( Parallel::IsServer() ) + { + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + } + HXSendRecvData( &zoneType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + } + + Zone * zone = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zone = new Zone(); + Global::zones.push_back( zone ); + LocalZone::global_zoneids.push_back( iZone ); + LocalZone::nZones = LocalZone::global_zoneids.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zone->nijk.push_back( isize[ m ] ); + } + } + + Grid * grid = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + grid = new Grid(); + Global::grids.push_back( grid ); + } + + BaseZone baseZone; + + int gZoneId = -1; + if ( Parallel::IsServer() ) + { + baseZone.zone_name = zonename; + gZoneId = Global::zone_names.FindBaseZone( baseZone ); + } + + HXSendRecvData( &gZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "gZoneId = " << gZoneId << "\n"; + } + + int ncoords = -1; + if ( Parallel::IsServer() ) + { + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + } + HXSendRecvData( &ncoords, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ncoords = " << ncoords << "\n"; + } + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + if ( Parallel::IsServer() ) + { + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + } + HXSendRecvData( coordname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &dataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "coordname = " << coordname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + } + + std::vector coord; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + coord.resize( nNodes * sizeof( double ) ); + } + + if ( Parallel::IsServer() ) + { + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + } + + HXSendRecvData( coord.data(), coord.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + Coor * coor = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord = coord; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + coor->DumpCoor(); + + if ( icoord == 0 ) + { + grid->x.resize( nNodes ); + coor->DumpCoorX( grid->x ); + } + } + } + + int nbocos = -1; + if ( Parallel::IsServer() ) + { + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + } + HXSendRecvData( &nbocos, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbocos = " << nbocos << "\n"; + } + + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + if ( Parallel::IsServer() ) + { + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + } + HXSendRecvData( &location, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + } + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + //std::vector normalIndex( index_dim, -1 ); + std::vector normalIndex; + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + if ( Parallel::IsServer() ) + { + normalIndex.resize( index_dim ); + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + } + + if ( ZoneState::IsValid( iZone ) ) + { + normalIndex.resize( index_dim ); + } + + HXSendRecvData( boconame, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &bocotype, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ptset_type, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &npnts, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalDataType, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &normalListSize, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( normalIndex.data(), index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( &ndataset, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "ndataset = " << ndataset << "\n"; + } + + std::vector normalList; + std::vector pnts; + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + if ( normalDataType == DataTypeNull ) + { + normalList.resize( sizeof( int ) ); + } + else + { + int nSize = nNodes * index_dim * sizeof( double ); + normalList.resize( nSize ); + } + pnts.resize( npnts * index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + } + + HXSendRecvData( pnts.data(), npnts * index_dim, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + } + HXSendRecvData( normalList.data(), normalList.size(), Parallel::serverid, ZoneState::GetProcID(iZone)); + + ZoneBc * zonebc = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + zonebc->bcType = bocotype; + for ( int i = 0; i < pnts.size(); ++ i ) + { + zonebc->pnts.push_back( pnts[ i ] ); + } + } + } + int n1to1 = -1; + if ( Parallel::IsServer() ) + { + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + } + + HXSendRecvData( &n1to1, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "n1to1 = " << n1to1 << "\n"; + } + + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range; + std::vector donor_range; + std::vector transform; + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + range.resize( npnts * index_dim ); + donor_range.resize( npnts * index_dim ); + transform.resize( index_dim ); + } + + if ( Parallel::IsServer() ) + { + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + } + + HXSendRecvData( connectname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donorname, 33, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( range.data(), range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( donor_range.data(), donor_range.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + HXSendRecvData( transform.data(), transform.size(), Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + if ( ZoneState::IsValid( iZone ) || Parallel::IsServer() ) + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "connectname = " << connectname << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "range = "; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "donor_range = "; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "transform = "; + for ( int i = 0; i < transform.size(); ++ i ) + { + std::cout << transform[ i ] << " "; + } + std::cout << "\n"; + } + + int gDonorZoneId = -1; + if ( Parallel::IsServer() ) + { + BaseZone baseZoneDonor; + baseZoneDonor.zone_name = donorname; + + gDonorZoneId = Global::zone_names.FindBaseZone( baseZoneDonor ); + } + + HXSendRecvData( &gDonorZoneId, 1, Parallel::serverid, ZoneState::GetProcID( iZone ) ); + + ZoneBc1To1 * zonebc_1to1 = nullptr; + if ( ZoneState::IsValid( iZone ) ) + { + zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + } + } + } + } + + { + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Global::zones.size() = " << Global::zones.size() << "\n"; + } + + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Field.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Field.cpp new file mode 100644 index 00000000..c359a811 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Field.cpp @@ -0,0 +1,142 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } + int kkk = 1; +} + +void Field::Solve( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Field.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Field.h new file mode 100644 index 00000000..084ec9bd --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Field.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void UpdateOldField(); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/LogFile.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include "Parallel.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; + +class OStream : public std::ostringstream +{ +public: + OStream() {} + ~OStream() {} +public: + void ClearAll() + { + this->clear(); + this->str(""); + } +}; + +OStream StrIO; +std::string GetPrjDirName( const std::string & fileName ); +bool DirExist( const std::string & dirName ); +void MakeDir( const std::string & dirName ); + +std::string GetPrjDirName( const std::string & fileName ) +{ + size_t pos = fileName.find_last_of("\\/"); + if ( std::string::npos == pos ) + { + return ""; + } + else + { + return fileName.substr( 0, pos ); + } +} + +bool DirExist( const std::string & dirName ) +{ +#ifdef _WINDOWS + bool flag = ( _access( dirName.c_str(), 0 ) == 0 ); + return flag; +#else + bool flag = ( access( dirName.c_str(), 0 ) == 0 ); + return flag; +#endif +} + +void MakeDir( const std::string & dirName ) +{ + int flag; +#ifdef _WINDOWS + flag = _mkdir( dirName.c_str() ); +#else + flag = mkdir( dirName.c_str(), S_IRWXU ); +#endif + if ( flag == 0 ) + { + std::cout << dirName << " directory has been created successfully !\n"; + } +} + +void CreateDirIfNeeded( std::string & prjFileName ) +{ + std::string prj_dir = GetPrjDirName( prjFileName ); + + if ( ! DirExist( prj_dir ) ) + { + MakeDir( prj_dir ); + } +} + + +void OpenLogFile( int logFileIndex, std::fstream & file ) +{ + static int ifReWrite = 0; + + StrIO.ClearAll(); + StrIO << "log/log" << logFileIndex << ".log"; + std::string fileName = StrIO.str(); + + std::ios_base::openmode openMode; + + if ( ifReWrite == 0 ) + { + CreateDirIfNeeded( fileName ); + + openMode = std::ios_base::out | std::ios_base::trunc; + + ifReWrite = 1; + } + else + { + openMode = std::ios_base::out | std::ios_base::app; + } + + file.open( fileName.c_str(), openMode ); + if ( ! file ) + { + std::cout << "could not open " << fileName << std::endl; + exit( 0 ); + } +} + +void CloseLogFile( std::fstream & file ) +{ + file.close(); + file.clear(); +} + +LogFile::LogFile() +{ +} + +LogFile::~LogFile() +{ +} + +void LogFile::Open() +{ + int pid = Parallel::pid; + OpenLogFile( pid, this->my_fstream ); +} + +void LogFile::Close() +{ + CloseLogFile( this->my_fstream ); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/LogFile.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/LogFile.h @@ -0,0 +1,27 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class LogFile +{ +public: + LogFile(); + ~LogFile(); + std::fstream my_fstream; +public: + void Open(); + void Close(); +}; + +template< typename T > +LogFile & operator << ( LogFile & f, const T & value ) +{ + f.Open(); + f.my_fstream << value; + f.Close(); + return f; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Parallel.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Parallel.cpp @@ -0,0 +1,54 @@ +#include "Parallel.h" +#include + +int Parallel::pid = 0; +int Parallel::nProc = 1; +int Parallel::serverid = 0; +int Parallel::tag = 0; + +void Parallel::Init() +{ +#ifdef HX_PARALLEL + int argc = 0; + char ** argv = 0; + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nProc ); + int len = -1; + char version[ MPI_MAX_LIBRARY_VERSION_STRING ]; + MPI_Get_library_version( version, &len ); + std::cout << "Hello, world! I am " << Parallel::pid << " of " << Parallel::nProc + << "(" << version << ", " << len << ")" << std::endl; +#endif +} + +void Parallel::Finalize() +{ +#ifdef HX_PARALLEL + MPI_Finalize(); +#endif +} + +bool Parallel::IsServer() +{ + return Parallel::pid == Parallel::serverid; +} + +void HXSendChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + MPI_Send( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvChar( void * data, int size, int pid, int tag ) +{ +#ifdef HX_PARALLEL + if ( size <= 0 ) return; + + MPI_Status status; + MPI_Recv( data, size, MPI_CHAR, pid, tag, MPI_COMM_WORLD, & status ); +#endif +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Parallel.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Parallel.h @@ -0,0 +1,78 @@ +#pragma once +#ifdef HX_PARALLEL +#include "mpi.h" +#endif +#include +#include "LogFile.h" + +class Parallel +{ +public: + static int pid; + static int nProc; + static int serverid; + static int tag; +public: + static void Init(); + static void Finalize(); +public: + static bool IsServer(); +}; + +void HXSendChar( void * data, int size, int pid, int tag ); +void HXRecvChar( void * data, int size, int pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag ); + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag ); + +template< typename T > +void HXSendData( T * field, int nElement, int recv_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXSendChar( field, buffer_size, recv_pid, tag ); +} + +template< typename T > +void HXRecvData( T * field, int nElement, int send_pid, int tag = 0 ) +{ + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + HXRecvChar( field, buffer_size, send_pid, tag ); +} + +template< typename T > +void HXSendRecvData( T * field, int nElement, int send_pid, int recv_pid, int tag = 0 ) +{ + if ( send_pid == recv_pid ) return; + + if ( nElement <= 0 ) return; + + int buffer_size = nElement * sizeof( T ); + + if ( Parallel::pid == send_pid ) + { + HXSendChar( field, buffer_size, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvChar( field, buffer_size, send_pid, tag ); + } +} + +template< typename T > +void HXBcastData( T * field, int nElement, int send_pid ) +{ + if ( nElement <= 0 ) return; + int buffer_size = nElement * sizeof( T ); +#ifdef HX_PARALLEL + MPI_Bcast( field, buffer_size, MPI_CHAR, send_pid, MPI_COMM_WORLD ); +#endif +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/README.txt b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/README.txt @@ -0,0 +1,3 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. + +PS D:\github\OneFLOW\example\1d-heat-equation\ftcs\cpp\multiblock\parallel\8blocks\01\build> mpiexec -n 8 .\Debug\testprj.exe diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Solver.cpp new file mode 100644 index 00000000..6035f616 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Solver.cpp @@ -0,0 +1,680 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +Solver::Solver() +{ + Parallel::Init(); +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d8blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +void Solver::InitTopo() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitTopo() " << "\n"; + + Global::donor_zone_sets.resize( LocalZone::nZones ); + Global::donor_zones.resize( LocalZone::nZones ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + int global_zoneid = LocalZone::global_zoneids[ iZone ]; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "iZone = " << iZone << " global_zoneid = " << global_zoneid << "\n"; + + Interface * interface = new Interface(); + interface->zoneid = global_zoneid; + Global::interfaces.push_back( interface ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nbc1to1s = " << nbc1to1s << "\n"; + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "zoneid = " << zoneid << " donor_zoneid = " << donor_zoneid << "\n"; + + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + int nInterfaces = interface->zoneList.size(); + interface->data_recv.resize( nInterfaces ); + interface->data_send.resize( nInterfaces ); + } + + for ( int iProc = 0; iProc < Parallel::nProc; ++ iProc ) + { + int nSize = -1; + if ( iProc == Parallel::pid ) + { + nSize = Global::facePairList.size(); + } + HXBcastData( &nSize, 1, iProc ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "nSize = " << nSize << "\n"; + std::vector tmp; + if ( iProc == Parallel::pid ) + { + tmp = Global::facePairList; + } + else + { + tmp.resize( nSize ); + } + + HXBcastData( tmp.data(), tmp.size(), iProc ); + Global::AddFacePairList( Global::mpi_facePairList, tmp ); + } + + for ( int i = 0; i < Global::mpi_facePairList.size(); ++ i ) + { + FacePair &facePair = Global::mpi_facePairList[ i ]; + Global::InsertFacePairMap( facePair ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + facePair.Print(); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterfaces = interface->local_faceids.size(); + for ( int iInterface = 0; iInterface < nInterfaces; ++ iInterface ) + { + int local_faceid = interface->local_faceids[ iInterface ]; + int proc_global_faceid = interface->proc_global_faceids[ iInterface ]; + FacePair & facePair = Global::facePairList[ proc_global_faceid ]; + int global_faceid = Global::InsertFacePairMap( facePair ); + interface->global_faceids.push_back( global_faceid ); + interface->global_local_face_map.insert( std::make_pair( global_faceid, local_faceid ) ); + } + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + std::set &donor_zoneSet = Global::donor_zone_sets[ iZone ]; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + donor_zoneSet.insert( donor_zoneid ); + } + + std::vector &donor_zones = Global::donor_zones[ iZone ]; + for ( std::set::iterator iter = donor_zoneSet.begin(); iter != donor_zoneSet.end(); ++ iter ) + { + donor_zones.push_back( *iter ); + } + + interface->neighbor_donor_zones = donor_zones; + + std::unordered_map donor_zonelocal; + + for ( int idonor = 0; idonor < donor_zones.size(); ++ idonor ) + { + int donor_zone = donor_zones[ idonor ]; + donor_zonelocal.insert( std::make_pair( donor_zone, idonor ) ); + } + int ndonors = donor_zones.size(); + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + neighbor_donorfaces.resize( ndonors ); + + std::vector> & sub_local_faceids = interface->sub_local_faceids; + sub_local_faceids.resize( ndonors ); + + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ineighbor = donor_zonelocal[ donor_zoneid ]; + std::vector &donorfaces = neighbor_donorfaces[ ineighbor ]; + int global_faceid = interface->global_faceids[ iFace ]; + donorfaces.push_back( global_faceid ); + int local_faceid = interface->local_faceids[ iFace ]; + + std::vector & sub_local_faces = sub_local_faceids[ ineighbor ]; + sub_local_faces.push_back( local_faceid ); + } + } + + Global::interfaceTopo.InitNeighborInfo(); + Global::interfaceTopo.SwapNeighborInfo(); + + int kkk = 1; +} + +void Solver::InitFields() +{ + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Solver::InitFields() ZoneState::nZones = " << ZoneState::nZones << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + } + + Boundary(); +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + //std::cout << "Parallel::pid = " << Parallel::pid << " "; + //std::cout << "it = " << it << " nt = " << Global::nt << "\n"; + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + Boundary(); + } +} + +void Solver::Boundary() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + ExchangeInterfaceField(); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->UpdateOldField(); + } +} + +void Solver::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + std::vector & send_to_zones = interface->send_to_zones; + int nsend_zones = send_to_zones.size(); + + std::vector> & donorfaces_for_send = interface->donorfaces_for_send; + std::vector> & donorijk_for_send = interface->donorijk_for_send; + std::vector> & donordata_for_send = interface->donordata_for_send; + + Field * field = Global::fields[ iZone ]; + + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = send_to_zones[ iSend ]; + std::vector & donorfaces = donorfaces_for_send[ iSend ]; + std::vector & donorijks = donorijk_for_send[ iSend ]; + std::vector & donordatas = donordata_for_send[ iSend ]; + + int nface = donorfaces.size(); + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int ijkpos = index_dim * i; + int i_donor_cell = donorijks[ ijkpos + 0 ]; + donordatas[ i ] = field->u[ i_donor_cell ]; + } + } + } +} + +void Solver::UpdateInterfaceField() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int ndonor_zones = Global::interfaceTopo.linkmap[ iZone ].size(); + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = Global::interfaceTopo.linkmap[ iZone ][ iNei ]; + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nsend = -1; + std::vector donordata; + if ( Parallel::pid != send_pid && Parallel::pid != recv_pid ) continue; + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Interface * interface = Global::interfaces[ local_zoneid ]; + donordata = interface->donordata_for_send[ iNei ]; + nsend = donordata.size(); + } + HXSendRecvData( &nsend, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + donordata.resize( nsend ); + } + HXSendRecvData( donordata.data(), donordata.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * donor_interface = Global::interfaces[ local_donor_zoneid ]; + int nSize = donor_interface->neighbor_donor_zones.size(); + int ipos = -1; + for ( int i = 0; i < nSize; ++ i ) + { + int nei_zone = donor_interface->neighbor_donor_zones[ i ]; + if ( nei_zone == iZone ) + { + ipos = i; + break; + } + } + + std::vector & neighbor_donorfaces = donor_interface->neighbor_donorfaces[ ipos ]; + std::vector & sub_local_faceids = donor_interface->sub_local_faceids[ ipos ]; + for ( int i = 0; i < neighbor_donorfaces.size(); ++ i ) + { + int local_faceid = sub_local_faceids[ i ]; + double donor_value = donordata[ i ]; + donor_interface->data_recv[ local_faceid ] = donor_value; + } + } + } + } +} + +void Solver::DownloadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + Field * field = Global::fields[ iZone ]; + + int nInterFaces = interface->data_recv.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + + double donor_value = interface->data_recv[ iFace ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( !ZoneState::IsValid( iZone ) && !Parallel::IsServer() ) continue; + + double xmin = 0.0; + double xmax = 0.0; + + if ( ZoneState::IsValid( iZone ) ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + Grid * grid = Global::grids[ local_zoneid ]; + int ni = grid->x.size(); + xmin = grid->x[ 0 ]; + xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + } + + HXSendRecvData( &xmin, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + HXSendRecvData( &xmax, 1, ZoneState::pids[ iZone ], Parallel::serverid ); + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmin = " << xmin << "\n"; + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // std::cout << "xmax = " << xmax << "\n"; + //} + + if ( Parallel::IsServer() ) + { + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + } + + //if ( Parallel::IsServer() ) + //{ + // std::cout << "Parallel::pid = " << Parallel::pid << " "; + // for ( int i = 0; i < xmin_list.size(); ++ i ) + // { + // std::cout << "(" << xmin_list[ i ] << "," << xmax_list[ i ] << ") "; + // } + // std::cout << "\n"; + //} + + if ( Parallel::IsServer() ) + { + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[ i ], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[ i ].second ); + } + } + + int kkk = 1; +} + +bool IsLastZone( int iZone ); +bool IsLastZone( int iZone ) +{ + return iZone == ZoneState::nZones - 1; +} + +void Post::AddVector( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + +void Post::GatherField() +{ + this->zoneids.resize( ZoneState::nZones ); + HXBcastData( this->zoneids.data(), this->zoneids.size(), Parallel::serverid ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "Post::GatherField() this->zoneids = \n"; + for ( int i = 0; i < this->zoneids.size(); ++ i ) + { + std::cout << this->zoneids[ i ] << " "; + } + std::cout << "\n"; + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + + if ( !ZoneState::IsValid( zoneid ) && !Parallel::IsServer() ) continue; + + int nSize = -1; + std::vector local_x; + std::vector local_u_e; + std::vector local_un; + std::vector local_u; + + if ( Parallel::pid == ZoneState::pids[ zoneid ] ) + { + int local_zoneid = ZoneState::g2lzoneids[ zoneid ]; + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( IsLastZone( iZone ) ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + else + { + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + local_x.push_back( xm ); + local_u_e.push_back( field->u_e[ i ] ); + local_un.push_back( field->un[ i ] ); + local_u.push_back( field->u[ i ] ); + } + } + } + nSize = local_x.size(); + } + + int send_pid = ZoneState::pids[ zoneid ]; + + HXSendRecvData( &nSize, 1, send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + local_x.resize( nSize ); + local_u_e.resize( nSize ); + local_un.resize( nSize ); + local_u.resize( nSize ); + } + + HXSendRecvData( local_x.data(), local_x.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u_e.data(), local_u_e.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_un.data(), local_un.size(), send_pid, Parallel::serverid ); + HXSendRecvData( local_u.data(), local_u.size(), send_pid, Parallel::serverid ); + + if ( Parallel::IsServer() ) + { + this->AddVector( this->x, local_x ); + this->AddVector( this->u_e, local_u_e ); + this->AddVector( this->un, local_un ); + this->AddVector( this->u, local_u ); + } + } +} + +void Post::DumpField() +{ + if ( !Parallel::IsServer() ) return; + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "Parallel::pid = " << Parallel::pid << " "; + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Solver.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Solver.h new file mode 100644 index 00000000..9914c1d7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void Boundary(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); +public: + void AddVector( std::vector & a, std::vector & b ); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/ZoneState.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/ZoneState.cpp @@ -0,0 +1,20 @@ +#include "ZoneState.h" +#include "Parallel.h" + +int ZoneState::nZones = 0; +std::vector ZoneState::pids; +std::vector ZoneState::g2lzoneids; + +bool ZoneState::IsValid( int zoneid ) +{ + return ZoneState::pids[ zoneid ] == Parallel::pid; +} + +int ZoneState::GetProcID( int zoneid ) +{ + return ZoneState::pids[ zoneid ]; +} + +int LocalZone::nZones = 0; +std::vector LocalZone::global_zoneids; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/ZoneState.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/ZoneState.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ZoneState +{ +public: + static int nZones; + static int zone_id; + static std::vector pids; + static std::vector g2lzoneids; //global zone id to local zone id +public: + static bool IsValid( int zoneid ); + static int GetProcID( int zoneid ); +}; + +class LocalZone +{ +public: + static int nZones; + static std::vector global_zoneids; +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/global.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/global.cpp @@ -0,0 +1,300 @@ +#include "global.h" +#include "CgnsGrid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; + +std::map Global::faceMap; +std::map Global::facePairMap; +std::vector Global::facePairList; +std::vector Global::mpi_facePairList; + +std::vector> Global::donor_zone_sets; +std::vector> Global::donor_zones; + +InterfaceTopo Global::interfaceTopo; + +bool Face::operator < ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return this->zone < rhs.zone; + } + + if ( this->i != rhs.i ) + { + return this->i < rhs.i; + } + + if ( this->j != rhs.j ) + { + return this->j < rhs.j; + } + + return this->k < rhs.k; +} + +bool Face::operator == ( const Face & rhs ) const +{ + if ( this->zone != rhs.zone ) + { + return false; + } + + if ( this->i != rhs.i ) + { + return false; + } + + if ( this->j != rhs.j ) + { + return false; + } + + return this->k == rhs.k; +} + +void Face::Print() +{ + std::cout << "(" << this->zone << "," << this->i << ")"; +} + +void FacePair::AddPair( const Face & face1, const Face & face2 ) +{ + if ( face1 < face2 ) + { + this->left = face1; + this->right = face2; + } + else + { + this->left = face2; + this->right = face1; + } +} + +bool FacePair::operator < ( const FacePair & rhs ) const +{ + if ( this->left == rhs.left || this->left == rhs.right ) + { + return false; + } + + return this->left < rhs.left; +} + +void FacePair::Print() +{ + this->left.Print(); + std::cout << " "; + this->right.Print(); + std::cout << "\n"; +} + +void InterfaceTopo::InitNeighborInfo() +{ + this->linkmap.resize( ZoneState::nZones ); + + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + if ( ! ZoneState::IsValid( iZone ) ) continue; + + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector & t = this->linkmap[ iZone ]; + t = interface->neighbor_donor_zones; + } +} + +void InterfaceTopo::SwapNeighborInfo() +{ + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int nNeighbor = donor_zones.size(); + + HXBcastData( &nNeighbor, 1, pid ); + + donor_zones.resize( nNeighbor ); + + HXBcastData( donor_zones.data(), donor_zones.size(), pid ); + } + + this->SwapNeighborDonorfaces(); +} + +void InterfaceTopo::SwapNeighborDonorfaces() +{ + int gl = 0; + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + + std::vector & donor_zones = this->linkmap[ iZone ]; + int ndonor_zones = donor_zones.size(); + + for ( int iNei = 0; iNei < ndonor_zones; ++ iNei ) + { + int donor_zone = donor_zones[ iNei ]; + int recv_pid = ZoneState::pids[ donor_zone ]; + int nInterFaces = 0; + std::vector donorfaces; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Interface * interface = Global::interfaces[ local_zoneid ]; + + std::vector> & neighbor_donorfaces = interface->neighbor_donorfaces; + + std::vector & neighbor_donorface = neighbor_donorfaces[ iNei ]; + + nInterFaces = neighbor_donorface.size(); + + donorfaces = neighbor_donorface; + } + + HXSendRecvData( &nInterFaces, 1, send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid && send_pid != recv_pid ) + { + donorfaces.resize( nInterFaces ); + } + + HXSendRecvData( donorfaces.data(), donorfaces.size(), send_pid, recv_pid ); + + if ( Parallel::pid == recv_pid ) + { + int local_donor_zoneid = ZoneState::g2lzoneids[ donor_zone ]; + Interface * interface_recv = Global::interfaces[ local_donor_zoneid ]; + interface_recv->SendGeom( iZone, donorfaces ); + } + } + } +} + + +void Interface::CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->local_faceids.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + Face face; + face.zone = zoneid; + face.i = i; + + int i_donor = index2[ 0 ]; + + Face face_donor; + face_donor.zone = donor_zoneid; + face_donor.i = i_donor; + + FacePair facePair; + facePair.AddPair( face, face_donor ); + + Global::facePairList.push_back( facePair ); + int nSize = Global::facePairList.size(); + this->proc_global_faceids.push_back( nSize - 1 ); + + int i_ghost_cell = i + 1; + int i_local_donor_cell = i - 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + i_local_donor_cell = i + 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + ijk_donors.push_back( i_local_donor_cell ); + + icount ++; + } +} + +void Interface::SendGeom( int zone, std::vector & donorfaces ) +{ + Interface * interface = this; + + std::vector & send_to_zones = interface->send_to_zones; + + send_to_zones.push_back( zone ); + interface->donorfaces_for_send.push_back( donorfaces ); + + int nface = donorfaces.size(); + std::vector sub_donorijk; + int index_dim = 1; + for ( int i = 0; i < nface; ++ i ) + { + int global_faceid = donorfaces[ i ]; + int local_faceid = interface->global_local_face_map[ global_faceid ]; + int ijkpos = index_dim * local_faceid; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + sub_donorijk.push_back( i_donor_cell ); + int kkk = 1; + } + + interface->donorijk_for_send.push_back( sub_donorijk ); + + std::vector sub_donordata( sub_donorijk.size() ); + interface->donordata_for_send.push_back( sub_donordata ); +} + +void Global::InsertFaceMap( const Face & face ) +{ + std::map::iterator iter; + iter = Global::faceMap.find( face ); + if ( iter == Global::faceMap.end() ) + { + int faceid = Global::faceMap.size(); + Global::faceMap.insert( std::make_pair( face, faceid ) ); + } +} + +int Global::InsertFacePairMap( const FacePair & facePair ) +{ + std::map::iterator iter; + iter = Global::facePairMap.find( facePair ); + if ( iter == Global::facePairMap.end() ) + { + int facePairId = Global::facePairMap.size(); + Global::facePairMap.insert( std::make_pair( facePair, facePairId ) ); + return facePairId; + } + return iter->second; +} + +void Global::AddFacePairList( std::vector & a, std::vector & b ) +{ + for ( int i = 0; i < b.size(); ++ i ) + { + a.push_back( b[ i ] ); + } +} + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/global.h b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/global.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class Face +{ +public: + int zone = 0; + int i = 0; + int j = 1; + int k = 1; +public: + bool operator < ( const Face & rhs ) const; + bool operator == ( const Face & rhs ) const; +public: + void Print(); +}; + +class FacePair +{ +public: + Face left; + Face right; +public: + bool operator < ( const FacePair & rhs ) const; + void AddPair( const Face &face1, const Face &face2); +public: + void Print(); +}; + +class Transform; + +class InterfaceTopo +{ +public: + std::vector> linkmap; +public: + void InitNeighborInfo(); + void SwapNeighborInfo(); + void SwapNeighborDonorfaces(); +}; + + +class Interface +{ +public: + int zoneid; + std::vector zoneList; + std::vector global_faceids; + std::vector mpi_global_faceids; + std::vector proc_global_faceids; + std::vector local_faceids; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector data_recv; + std::vector data_send; + std::unordered_map global_local_face_map; +public: + std::vector neighbor_donor_zones; + std::vector> neighbor_donorfaces; + std::vector> sub_local_faceids; + std::vector send_to_zones; + std::vector> donorfaces_for_send; + std::vector> donorijk_for_send; + std::vector> donordata_for_send; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; +public: + static std::map faceMap; + static std::map facePairMap; + static std::vector facePairList; + static std::vector mpi_facePairList; + static std::vector> donor_zone_sets; + static std::vector> donor_zones; + static InterfaceTopo interfaceTopo; +public: + static int nt; + static int cell_dim; + static int phys_dim; +public: + static void InsertFaceMap( const Face & face ); + static int InsertFacePairMap( const FacePair & facePair ); + static void AddFacePairList( std::vector & a, std::vector & b ); +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/heat1d4blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/heat1d4blocksv1.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/heat1d4blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/heat1d8blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/heat1d8blocksv1.cgns new file mode 100644 index 00000000..4dc174d4 Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/heat1d8blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/main.cpp b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/main.cpp @@ -0,0 +1,9 @@ +#include "Solver.h" +#include "Parallel.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/plot.py b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/multiblock/parallel/8blocks/01a/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/single_block/01/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/single_block/01/CgnsGrid.h new file mode 100644 index 00000000..42633021 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/CgnsGrid.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/Field.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01/Field.cpp new file mode 100644 index 00000000..25c64637 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/Field.cpp @@ -0,0 +1,173 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + + this->PhysicalBoundary( zone ); + + this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) +{ + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/Field.h b/example/1d-heat-equation/ftcs/cpp/single_block/01/Field.h new file mode 100644 index 00000000..fd3c5004 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/Field.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void AddData( PointFactory & ptfactory, Grid * grid, std::vector & global_x, std::vector & global_ue, std::vector & global_un ); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/README.txt b/example/1d-heat-equation/ftcs/cpp/single_block/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01/Solver.cpp new file mode 100644 index 00000000..4382ad01 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/Solver.cpp @@ -0,0 +1,381 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d1blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceField(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->Solve( zone ); + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceValue() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/Solver.h b/example/1d-heat-equation/ftcs/cpp/single_block/01/Solver.h new file mode 100644 index 00000000..3ce472a7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); + void ExchangeInterfaceValue(); +public: + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/global.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/global.h b/example/1d-heat-equation/ftcs/cpp/single_block/01/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/heat1d1blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/single_block/01/heat1d1blocksv1.cgns new file mode 100644 index 00000000..a367704f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/single_block/01/heat1d1blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/main.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/plot.py b/example/1d-heat-equation/ftcs/cpp/single_block/01/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/single_block/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/single_block/01a/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01a/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/single_block/01a/CgnsGrid.h new file mode 100644 index 00000000..42633021 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/CgnsGrid.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/Field.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01a/Field.cpp new file mode 100644 index 00000000..31f53a1f --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/Field.cpp @@ -0,0 +1,174 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid->x; + this->dx = x[ 1 ] - x[ 0 ]; + this->dt = dx / 10.0; + this->t = 1.0; + this->nt = std::round( t / dt ); + std::cout << "nt = " << nt << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 15 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 15 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * xm ); //theory solution + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + + this->PhysicalBoundary( zone ); + + this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::AddData( PointFactory &ptfactory, Grid * grid, std::vector &global_x, std::vector &global_ue, std::vector &global_un ) +{ + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + bool flag = ptfactory.FindPoint( Point( xm ) ); + if ( i == 0 || ( i == ni - 1 ) ) + { + if ( ! flag ) + { + ptfactory.AddPoint( Point( xm ) ); + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } + else + { + global_x.push_back( grid->x[ i ] ); + global_ue.push_back( this->u_e[ i ] ); + global_un.push_back( this->un[ i ] ); + } + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/Field.h b/example/1d-heat-equation/ftcs/cpp/single_block/01a/Field.h new file mode 100644 index 00000000..fd3c5004 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/Field.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void AddData( PointFactory & ptfactory, Grid * grid, std::vector & global_x, std::vector & global_ue, std::vector & global_un ); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/README.txt b/example/1d-heat-equation/ftcs/cpp/single_block/01a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01a/Solver.cpp new file mode 100644 index 00000000..4382ad01 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/Solver.cpp @@ -0,0 +1,381 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d1blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceField(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + field->Solve( zone ); + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::ExchangeInterfaceValue() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + interfacezone->left_u.resize( nInterFace ); + interfacezone->right_u.resize( nInterFace ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + InterFaceZone * interfacezone = Global::interfacezones[ iZone ]; + int nInterFace = interfacezone->left_zones.size(); + + for ( int i = 0; i < nInterFace; ++ i ) + { + int left_cell = interfacezone->left_cells[ i ]; + int donor_zoneid = interfacezone->right_zones[ i ]; + int donor_cell = interfacezone->right_cells[ i ]; + Field * donor_field = Global::fields[ donor_zoneid ]; + + interfacezone->left_u[ i ] = field->u[ left_cell ]; + interfacezone->right_u[ i ] = donor_field->u[ donor_cell ]; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + std::string csvname = "field_final.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/Solver.h b/example/1d-heat-equation/ftcs/cpp/single_block/01a/Solver.h new file mode 100644 index 00000000..3ce472a7 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/Solver.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); + void ExchangeInterfaceValue(); +public: + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/global.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01a/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/global.h b/example/1d-heat-equation/ftcs/cpp/single_block/01a/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/heat1d1blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/single_block/01a/heat1d1blocksv1.cgns new file mode 100644 index 00000000..a367704f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/single_block/01a/heat1d1blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/main.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01a/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/plot.py b/example/1d-heat-equation/ftcs/cpp/single_block/01a/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01a/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/single_block/01a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01a/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/single_block/01b/CMakeLists.txt new file mode 100644 index 00000000..ee758c31 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + global.h global.cpp + CgnsGrid.h CgnsGrid.cpp + Field.h Field.cpp + Solver.h Solver.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/CgnsGrid.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01b/CgnsGrid.cpp new file mode 100644 index 00000000..e186c2f4 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/CgnsGrid.cpp @@ -0,0 +1,578 @@ +#include "CgnsGrid.h" +#include "cgnslib.h" +#include "global.h" +#include +#include + + +Region::Region() +{ +} + +Region::~Region() +{ +} + +Region & Region::operator = ( const Region & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +void Region::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + this->start.resize( index_dim ); + this->end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +void Region::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +void Coor::DumpCoorX( std::vector &x ) +{ + double * xd = reinterpret_cast( const_cast( coord.data() ) ); + for ( int i = 0; i < this->nNodes; ++ i ) + { + x[ i ] = xd[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +int Trans::M[ 3 ][ 3 ]; +std::vector Trans::transform; + +int Trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int Trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void Trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + Trans::M[ i ][ j ] = 0; + } + } +} + +void Trans::CalcTransformMatrix() +{ + int dim = Trans::transform.size(); + if ( dim == 1 ) + { + int a = Trans::transform[ 0 ]; + int sgna = Trans::sgn( a ); + int a1 = Trans::del( a, 1 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = Trans::transform[ 0 ]; + int b = Trans::transform[ 1 ]; + int c = Trans::transform[ 2 ]; + int sgna = Trans::sgn( a ); + int sgnb = Trans::sgn( b ); + int sgnc = Trans::sgn( c ); + int a1 = Trans::del( a, 1 ); + int a2 = Trans::del( a, 2 ); + int a3 = Trans::del( a, 3 ); + int b1 = Trans::del( b, 1 ); + int b2 = Trans::del( b, 2 ); + int b3 = Trans::del( b, 3 ); + int c1 = Trans::del( c, 1 ); + int c2 = Trans::del( c, 2 ); + int c3 = Trans::del( c, 3 ); + Trans::M[ 0 ][ 0 ] = sgna * a1; + Trans::M[ 1 ][ 0 ] = sgna * a2; + Trans::M[ 2 ][ 0 ] = sgna * a3; + Trans::M[ 0 ][ 1 ] = sgnb * b1; + Trans::M[ 1 ][ 1 ] = sgnb * b2; + Trans::M[ 2 ][ 1 ] = sgnb * b3; + Trans::M[ 0 ][ 2 ] = sgnc * c1; + Trans::M[ 1 ][ 2 ] = sgnc * c2; + Trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +Transform::Transform() +{ + //int dim = Dim::dim; + int dim = 1; + this->diff.resize( dim ); + this->mul.resize( dim ); +} + +Transform::~Transform() +{ + ; +} + +void Transform::Init() +{ + Trans::ZeroMatrix(); + Trans::transform = this->transform; + Trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = Trans::M[ i ][ j ]; + } + } +} + +void Transform::MapIndex( std::vector & index1, std::vector & index2 ) +{ + int dim = index1.size(); + for ( int m = 0; m < dim; ++ m ) + { + this->diff[ m ] = index1[ m ] - this->begin1[ m ]; + } + + this->Multiply( diff, this->mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = this->mul[ m ] + this->begin2[ m ]; + } + +} + +void Transform::Multiply( std::vector & a, std::vector & b ) +{ + int dim = a.size(); + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += this->Mt[ i ][ j ] * a[ j ]; + } + } +} + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[ 33 ]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[ i ] << "\n"; + } + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[ zoneType ] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + Grid * grid = new Grid(); + Global::grids.push_back( grid ); + + BC * bc = new BC(); + Global::bcs.push_back( bc ); + + InterFaceZone * interfacezone = new InterFaceZone(); + Global::interfacezones.push_back( interfacezone ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[ dataType ] << "\n"; + //std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + + coor->DumpCoor(); + if ( icoord == 0 ) + { + coor->DumpCoorX( grid->x ); + } + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[ bocotype ] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + for ( int i = 0; i < pnts.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ pnts[ i ] - 1 ] ); + } + + if ( index_dim == 1 ) + { + int p1 = pnts[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + + bc->bctypes.push_back( bocotype ); + bc->faceids.push_back( p1 - 1 ); + } + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + for ( int i = 0; i < range.size(); ++ i ) + { + Global::boundary_points.AddPoint( grid->x[ range[ i ] - 1 ] ); + } + + BaseZone baseZone; + baseZone.zone_name = donorname; + + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + if ( index_dim == 1 ) + { + int p1 = range[ 0 ]; + double x1 = grid->x[ p1 - 1 ]; + int id = Global::boundary_points.AddPoint( x1 ); + Face face; + std::vector nodes; + nodes.push_back( id ); + face.AddFace( nodes ); + Global::boundary_faces.AddFace( face ); + Global::inter_faces.AddFace( face ); + + bc->bctypes.push_back( BCTypeUserDefined ); + bc->faceids.push_back( p1 - 1 ); + + interfacezone->face_ids.push_back( p1 ); + + interfacezone->left_zones.push_back( gZoneId ); + interfacezone->left_cells.push_back( p1 - 1 ); + + int q = donor_range[ 0 ]; + interfacezone->right_zones.push_back( gDonorZoneId ); + interfacezone->right_cells.push_back( q - 1 ); + } + } + } + } + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/CgnsGrid.h b/example/1d-heat-equation/ftcs/cpp/single_block/01b/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/CgnsGrid.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +class Region +{ +public: + Region(); + ~Region(); +public: + std::vector start; + std::vector end; +public: + Region & operator = ( const Region & rhs ); + void SetRegion( std::vector & pnts ); + void Print(); +}; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); + void DumpCoorX( std::vector & x ); +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + int zoneIndex; + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class Trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class Transform +{ +public: + Transform(); + ~Transform(); +private: + std::vector diff; + std::vector mul; +public: + int Mt[ 3 ][ 3 ]; + std::vector begin1; + std::vector begin2; + std::vector transform; +public: + void Init(); + void MapIndex( std::vector & index1, std::vector & index2 ); + void Multiply( std::vector & a, std::vector & b ); +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/Field.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01b/Field.cpp new file mode 100644 index 00000000..ac6e1419 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/Field.cpp @@ -0,0 +1,248 @@ +#include "Field.h" +#include "CgnsGrid.h" + +int Para::nt = -1; +double Para::dx = 0; +double Para::dt = 0; +double Para::t = 0; +double Para::alpha = 0; +double Para::beta = 0; + +void Para::Init() +{ + Para::dx = 0.025; + Para::dt = dx / 10.0; + Para::t = 1.0; + //Para::nt = std::round( t / dt ); + Para::nt = 2; + //Para::nt = 1; +} + +void GenGrid( std::vector & gx ); +void GenGrid( std::vector & gx ) +{ + const int ni = 81; + gx.resize( ni ); + + double x_l = -1.0; + double x_r = 1.0; + + double dx = ( x_r - x_l ) / ( ni - 1 ); + + for ( int i = 0; i < ni; ++ i ) + { + gx[ i ] = x_l + i * dx; + } +} + +void Field::ModifyGrid( Grid * grid ) +{ + std::vector globalx; + GenGrid( globalx ); + + this->ni = grid->x.size(); + + int ishift = 0; + + if ( grid->zoneIndex == 1 ) + { + ishift = ni - 1; + } + + for ( int i = 0; i < ni; ++ i ) + { + grid->x[ i ] = globalx[ i + ishift ]; + } +} + +void Field::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + this->ModifyGrid( grid ); + + std::vector & x = grid->x; + //this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + //this->dt = dx / 10.0; + //this->t = 1.0; + //this->nt = std::round( t / dt ); + + this->dx = Para::dx; + this->dt = Para::dt; + this->t = Para::t; + this->nt = Para::nt; + + double total_time = nt * dt; + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->t = " << this->t << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "total_time = " << std::setprecision( 25 ) << total_time << "\n"; + + Global::nt = nt; + + this->alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + this->beta = this->alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision( 25 ) << this->alpha << "\n"; + std::cout << "beta = " << std::setprecision( 25 ) << this->beta << "\n"; + + int nghost = 2; + int ni_total = ni + nghost; + + u_e.resize( ni_total ); + u.resize( ni_total ); + un.resize( ni_total ); + + // 0 1 2 ... ni-1 ni ni+1 + + int ist = 1; + int ied = ni; + + // 0(bc) 1(ist) 2 3 ... ni + + for ( int i = ist; i <= ied; ++ i ) + { + double xm = x[ i - ist ]; + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * xm ); //theory solution + if ( std::abs( xm - 0.2 ) < 1.0e-5 ) + { + double term1 = xm; + double term2 = std::sin( std::numbers::pi * xm ); + double term3 = std::exp( -total_time ); + double term4 = term2 * term3; + std::cout << "this->dx = " << std::setprecision( 25 ) << this->dx << "\n"; + std::cout << "x[0] = " << std::setprecision( 25 ) << x[ 0 ] << "\n"; + std::cout << "x[1] = " << std::setprecision( 25 ) << x[ 1 ] << "\n"; + std::cout << "this->dt = " << std::setprecision( 25 ) << this->dt << "\n"; + std::cout << "total_time = " << std::setprecision( 25 ) << total_time << "\n"; + std::cout << "term1 = " << std::setprecision( 25 ) << term1 << "\n"; + std::cout << "term2 = " << std::setprecision( 25 ) << term2 << "\n"; + std::cout << "term3 = " << std::setprecision( 25 ) << term3 << "\n"; + std::cout << "term4 = " << std::setprecision( 25 ) << term4 << "\n"; + } + u[ i ] = - std::sin( std::numbers::pi * xm ); //initial condition @ t=0 + } +} + +void Field::Solve( Zone * zone ) +{ + int nghost = 2; + int ni_total = ni + nghost; + + int ist = 1; + int ied = ni; + + for ( int i = ist; i <= ied; ++ i ) + { + double term1 = un[ i - 1 ]; + double term2 = un[ i ]; + double term3 = un[ i + 1 ]; + double term4 = term1 -2.0 * term2 + term3; + double term5 = beta * term4; + double term6 = term2 + term5; + if ( ( zone->zoneIndex == 0 && i== 41 ) ) + { + std::cout << "zone->zoneIndex = " << zone->zoneIndex << "\n"; + std::cout << "term1 = " << std::setprecision( 25 ) << term1 << "\n"; + std::cout << "term2 = " << std::setprecision( 25 ) << term2 << "\n"; + std::cout << "term3 = " << std::setprecision( 25 ) << term3 << "\n"; + std::cout << "term4 = " << std::setprecision( 25 ) << term4 << "\n"; + std::cout << "term5 = " << std::setprecision( 25 ) << term5 << "\n"; + std::cout << "term6 = " << std::setprecision( 25 ) << term6 << "\n"; + } + //u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + u[ i ] = term6; + } + + this->PhysicalBoundary( zone ); + + this->Update( un, u ); +} + +void Field::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + //std::cout << "zonebc->bcType = " << zonebc->bcType << "\n"; + Region region; + region.SetRegion( zonebc->pnts ); + //region.Print(); + Boundary( region, zonebc->bcType ); + } +} + +void Field::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate ) + { + this->OutflowBc( region ); + } +} + +void Field::InflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + int kkk = 1; + } +} + +void Field::OutflowBc( Region ®ion ) +{ + int index_dim = region.start.size(); + if ( index_dim != 1 ) return; + int st = region.start[ 0 ]; + int ed = region.end[ 0 ]; + for ( int i = st; i <= ed; ++ i ) + { + int idir = 1; + if ( i == 1 ) + { + idir = -1; + } + int ighost = i + idir; + int iinner = i - idir; + //this->u[ i ] = 0.0; + this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + std::vector & x = grid->x; + //compute L2 norm of the error + std::vector u_error( ni ); + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } +} + +void Field::Update( std::vector &un, std::vector &u ) +{ + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/Field.h b/example/1d-heat-equation/ftcs/cpp/single_block/01b/Field.h new file mode 100644 index 00000000..45c9da82 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/Field.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include +#include +#include "global.h" +#include "cgnslib.h" +#include "CgnsGrid.h" + +class Zone; +class Grid; + +class Para +{ +public: + static int nt; + static double dx, dt, t; + static double alpha, beta; +public: + static void Init(); +}; + +class Field +{ +public: + std::vector u_e; + std::vector u, un; + std::vector error; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void ModifyGrid( Grid * grid ); + void Init( Grid * grid ); + + void Solve( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + + void PostProcess( Grid * grid ); + void Update( std::vector & un, std::vector & u ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/README.txt b/example/1d-heat-equation/ftcs/cpp/single_block/01b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/Solver.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01b/Solver.cpp new file mode 100644 index 00000000..78058e55 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/Solver.cpp @@ -0,0 +1,377 @@ +#include "Solver.h" +#include + +double compute_l2norm( int ni, std::vector & r ) +{ + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; +} + +double compute_max_error( int ni, std::vector & u_error ) +{ + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveMultiZones(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../heat1d1blocksv1.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); + int nZones = Global::grids.size(); + PointFactory ptfactory; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + grid->zoneIndex = iZone; + int ni = grid->x.size(); + for ( int i = 0; i < ni; ++ i ) + { + int pid = ptfactory.AddPoint( Point( grid->x[ i ] ) ); + } + int kkk = 1; + } +} + +void Solver::InitTopo() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Interface * interface = new Interface(); + Global::interfaces.push_back( interface ); + + IJK * ijk = new IJK(); + Global::ijks.push_back( ijk ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Zone * zone = Global::zones[ iZone ]; + Interface * interface = Global::interfaces[ iZone ]; + + int nbc1to1s = zone->bc1to1s.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * bc1to1 = zone->bc1to1s[ ibc1to1 ]; + int zoneid = bc1to1->zoneid; + int donor_zoneid = bc1to1->donor_zoneid; + Region region; + region.SetRegion( bc1to1->pnts ); + + Region donor_region; + donor_region.SetRegion( bc1to1->donor_pnts ); + + Transform transform; + transform.begin1 = region.start; + transform.begin2 = donor_region.start; + transform.transform = bc1to1->transform; + transform.Init(); + + interface->CalcInterface( &transform, region.start, region.end, donor_zoneid ); + } + } +} + +void Solver::InitFields() +{ + Para::Init(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = new Field(); + Global::fields.push_back( field ); + } + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->Init( grid ); + Zone * zone = Global::zones[ iZone ]; + field->PhysicalBoundary( zone ); + } + + ExchangeInterfaceField(); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + field->Update( field->un, field->u ); + } +} + +void Solver::SolveMultiZones() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + ExchangeInterfaceField(); + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->Solve( zone ); + } + } +} + +void Solver::ExchangeInterfaceField() +{ + int nZones = Global::interfaces.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + + Interface * interface = Global::interfaces[ iZone ]; + int nInterFaces = interface->zoneList.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int donor_zoneid = interface->zoneList[ iFace ]; + int ijkpos = index_dim * iFace; + int i_ghost_cell = interface->ijk_ghosts[ ijkpos + 0 ]; + int i_donor_cell = interface->ijk_donors[ ijkpos + 0 ]; + + Field * donor_field = Global::fields[ donor_zoneid ]; + + double donor_value = donor_field->u[ i_donor_cell ]; + field->u[ i_ghost_cell ] = donor_value; + } + } +} + +void Solver::PostProcess() +{ + Post post; + post.Process(); +} + +void Solver::PrintField( std::vector &f ) +{ + int icount = 0; + for ( int i = 0; i < f.size(); ++ i ) + { + std::cout << std::setprecision(15) << f[ i ] << " "; + icount ++; + if ( icount % 5 == 0 ) + { + std::cout << "\n"; + } + } + std::cout << "\n"; + std::cout << "\n"; +} + + +void Post::Process() +{ + this->ReorderZones(); + this->GatherField(); + this->DumpField(); +} + +void Post::ReorderZones() +{ + int nZones = Global::grids.size(); + std::vector xmin_list; + std::vector xmax_list; + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + int ni = grid->x.size(); + double xmin = grid->x[ 0 ]; + double xmax = grid->x[ 0 ]; + int imin = 0; + int imax = 0; + for ( int i = 0; i < ni; ++ i ) + { + if ( xmin > grid->x[ i ] ) + { + xmin = grid->x[ i ]; + imin = i; + } + if ( xmax < grid->x[ i ] ) + { + xmax = grid->x[ i ]; + imax = i; + } + } + xmin_list.push_back( xmin ); + xmax_list.push_back( xmax ); + } + std::vector> pairs; + int nSize = xmin_list.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pairs.push_back( std::make_pair( xmin_list[i], i ) ); + } + + std::sort( pairs.begin(), pairs.end() ); + + for ( int i = 0; i < nSize; ++ i ) + { + this->zoneids.push_back( pairs[i].second ); + } + + int kkk = 1; +} + +void Post::GatherField() +{ + int nZones = Global::grids.size(); + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + int zoneid = this->zoneids[ iZone ]; + Grid * grid = Global::grids[ zoneid ]; + Field * field = Global::fields[ zoneid ]; + + int ni = grid->x.size(); + + int ist = 1; + int ied = ni; + + int dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( iZone == nZones - 1 ) + { + for ( int i = ist; i <= ied; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + + } + else + { + for ( int i = ist; i <= ied - 1; ++ i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } + else + { + if ( iZone == nZones - 1 ) + { + for ( int i = ied; i >= ist; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + for ( int i = ied; i >= ist + 1; -- i ) + { + double xm = grid->x[ i - ist ]; + this->x.push_back( xm ); + this->u_e.push_back( field->u_e[ i ] ); + this->un.push_back( field->un[ i ] ); + this->u.push_back( field->u[ i ] ); + } + } + } +} + +void Post::DumpField() +{ + int ni_total = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //compute L2 norm of the error + std::vector u_error( ni_total ); + for ( int i = 0; i < ni_total; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + this->DumpErrorDetails( u_error ); + + //std::string csvname = "field_final.csv"; + //this->DumpCsvFile( csvname, x, u_e, un, u_error ); + //std::string csvname_test = "field_final_test.csv"; + //this->DumpCsvFile( csvname_test, x, u_e, un, u, u_error ); + + std::string csvname = "field_final0.csv"; + this->DumpCsvFile( csvname, x, u_e, un, u_error ); + std::string csvname_test = "field_final_test0.csv"; + this->DumpCsvFile( csvname_test, x, u_e, un, u, u_error ); + +} + +void Post::DumpErrorDetails( std::vector &u_error ) +{ + int ni = u_error.size(); + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], uerror[i] ); + } + file.close(); +} + +void Post::DumpCsvFile( const std::string &filename, std::vector &x, std::vector &ue, std::vector &un, std::vector &u, std::vector &uerror ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + std::format_to(std::ostream_iterator(file), "x ue un u uerror\n"); + for ( int i = 0; i < x.size(); ++ i ) + { + //std::format_to(std::ostream_iterator(file), "{:.16f} {:.16f} {:.16f} {:.16f}\n", x[i], ue[i], un[i], uerror[i] ); + std::format_to(std::ostream_iterator(file), "{:.20f} {:.20f} {:.20f} {:.20f} {:.20f}\n", x[i], ue[i], un[i], u[i], uerror[i] ); + } + file.close(); +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/Solver.h b/example/1d-heat-equation/ftcs/cpp/single_block/01b/Solver.h new file mode 100644 index 00000000..a0d8ad69 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/Solver.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +class Solver +{ +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveMultiZones(); +public: + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +}; + + +class Post +{ +public: + std::vector zoneids; + std::vector x; + std::vector u_e; + std::vector un; + std::vector u; +public: + void Process(); + void ReorderZones(); + void GatherField(); + void DumpField(); + void DumpErrorDetails( std::vector & u_error ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & uerror ); + void DumpCsvFile( const std::string & filename, std::vector & x, std::vector & ue, std::vector & un, std::vector & u, std::vector & uerror ); +}; \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/global.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01b/global.cpp new file mode 100644 index 00000000..be237bec --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/global.cpp @@ -0,0 +1,59 @@ +#include "global.h" +#include "CgnsGrid.h" + +std::vector Global::grids; +std::vector Global::fields; +std::vector Global::bcs; +std::vector Global::interfacezones; +PointFactory Global::boundary_points; +FaceList Global::boundary_faces; +FaceList Global::inter_faces; + +int Global::nt = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +BaseZoneList Global::zone_names; +std::vector Global::interfaces; +std::vector Global::ijks; + +void Interface::CalcInterface( Transform * transform, std::vector &start, std::vector &end, int donor_zoneid ) +{ + int ist = start[ 0 ]; + int ied = end[ 0 ]; + int dim = start.size(); + std::vector index1( dim ); + std::vector index2( dim ); + + int icount = this->zoneList.size(); + for ( int i = ist; i <= ied; ++ i ) + { + int faceid = icount; + this->zoneList.push_back( donor_zoneid ); + this->faceidList.push_back( faceid ); + index1[ 0 ] = i; + transform->MapIndex( index1, index2 ); + int i_donor = index2[ 0 ]; + + int i_ghost_cell = i + 1; + + if ( i == 1 ) + { + i_ghost_cell = i - 1; + } + ijk_ghosts.push_back( i_ghost_cell ); + + int i_donor_cell = i_donor - 1; + + if ( i_donor == 1 ) + { + i_donor_cell = i_donor + 1; + } + + this->ijk_donors.push_back( i_donor_cell ); + + + icount ++; + } +} \ No newline at end of file diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/global.h b/example/1d-heat-equation/ftcs/cpp/single_block/01b/global.h new file mode 100644 index 00000000..665ba466 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/global.h @@ -0,0 +1,239 @@ +#pragma once +#include +#include +#include +#include +#include "CgnsGrid.h" + +class Grid; + +class Point +{ +public: + typedef Point point_type; + using value_type = double; +public: + Point() + { + this->x = 0; + } + Point( const value_type & x ) + { + this->x = x; + } +public: + value_type x; +public: + bool operator < ( const Point & rhs ) const + { + value_type dx = x - rhs.x; + value_type diff = 1.0e-10; + + if ( std::abs( dx ) > diff ) return x < rhs.x; + + return false; + } +}; + +class PointFactory +{ +public: + using value_type = double; + using point_type = Point; + using iterator = std::map< point_type, int >::iterator; +protected: + std::map< point_type, int > pointList; + std::vector pointArray; +public: + int GetNPoints() { return pointArray.size(); } + bool FindPoint( const point_type & point ) + { + iterator iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +private: + bool FindPoint( const point_type & point, iterator & iter ) + { + iter = pointList.find( point ); + if ( iter == pointList.end() ) + { + return false; + } + return true; + } +public: + int AddPoint( const point_type & point ) + { + PointFactory::iterator iter; + if ( FindPoint( point, iter ) ) + { + return iter->second; + } + else + { + int index = this->GetNPoints(); + + pointList.insert( std::make_pair(point, index) ); + pointArray.push_back( point ); + + return index; + } + } +}; + +class Face +{ +public: + std::vector nodes; + std::vector sorted_nodes; +public: + void AddFace( std::vector & nodes ) + { + this->nodes = nodes; + this->sorted_nodes = nodes; + std::sort( this->sorted_nodes.begin(), this->sorted_nodes.end() ); + } + bool operator < ( const Face & rhs ) const + { + return this->sorted_nodes < rhs.sorted_nodes; + } +}; + +class FaceList +{ +public: + std::map face_map; +public: + void AddFace( const Face & face ) + { + std::map::iterator iter; + iter = face_map.find( face ); + if ( iter == face_map.end() ) + { + int id = face_map.size(); + face_map.insert( std::make_pair( face, id ) ); + } + } +}; + +class BaseZone +{ +public: + //int baseId; + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + //if ( this->baseId != rhs.baseId ) + //{ + // return this->baseId < rhs.baseId; + //} + + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class BC +{ +public: + std::vector bctypes; + std::vector faceids; +}; + +class Grid +{ +public: + int zoneIndex; + std::vector x; +}; + +class InterFaceZone +{ +public: + std::vector face_ids; + std::vector left_zones; + std::vector right_zones; + std::vector left_cells; + std::vector right_cells; + std::vector left_u; + std::vector right_u; +}; + +class Transform; + +class Interface +{ +public: + std::vector zoneList; + std::vector faceidList; + std::vector ijkList; + std::vector ijk_ghosts; + std::vector ijk_donors; + std::vector uList; +public: + void CalcInterface( Transform * transform, std::vector & start, std::vector & end, int donor_zoneid ); +}; + +class IJK +{ +public: + std::vector iList; + std::vector jList; + std::vector kList; +}; + +class Field; +class BC; +class InterFaceZone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; + static std::vector bcs; + static std::vector interfacezones; + static PointFactory boundary_points; + static FaceList boundary_faces; + static FaceList inter_faces; +public: + static std::vector zones; + static BaseZoneList zone_names; + static std::vector interfaces; + static std::vector ijks; +public: + static int nt; + static int cell_dim; + static int phys_dim; +}; + diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/heat1d1blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/single_block/01b/heat1d1blocksv1.cgns new file mode 100644 index 00000000..a367704f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/single_block/01b/heat1d1blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/main.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/01b/main.cpp new file mode 100644 index 00000000..5ff48a4e --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/main.cpp @@ -0,0 +1,12 @@ +#include "cgnslib.h" +#include "global.h" +#include "CgnsGrid.h" +#include "Field.h" +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Run(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/plot.py b/example/1d-heat-equation/ftcs/cpp/single_block/01b/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/plot.py @@ -0,0 +1,58 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +x_list = [] +ue_list = [] +un_list = [] +uerror_list = [] + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + #print(row) + #print(row[0]) + #print(row[0], row[1], row[2], row[3]) + if ( icount != 0 ) : + x_list.append(row[0]) + ue_list.append(row[1]) + un_list.append(row[2]) + uerror_list.append(row[3]) + icount += 1 + +ni = icount - 1 +print("ni=",ni) + +x = np.zeros( ni ) +ue = np.zeros( ni ) +un = np.zeros( ni ) +uerror = np.zeros( ni ) + +for i in range(0, ni): + x[i] = float(x_list[i]) + ue[i] = float(ue_list[i]) + un[i] = float(un_list[i]) + uerror[i] = float(uerror_list[i]) + +plt.figure("OneFLOW-CFD Solver", figsize=(10, 4), dpi=100) +plt.subplot(1, 2, 1) +plt.plot(x, ue, "k-", linewidth=1.0, label="Exact solution") +plt.scatter(x, un, facecolor="none", edgecolor="blue", s=20, linewidths=0.5, label="FTCS solution") +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Solution field") +plt.legend() +plt.tight_layout() + +plt.subplot(1, 2, 2) +plt.scatter(x, np.abs(uerror), facecolor="none", edgecolor="green", s=20, linewidths=0.5) +plt.ylabel(r"$\epsilon$") +plt.xlabel("$x$") +plt.title("Discretization error") +plt.tight_layout() +plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) + +plt.show(); + + diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/01b/plotting2.jl b/example/1d-heat-equation/ftcs/cpp/single_block/01b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/01b/plotting2.jl @@ -0,0 +1,49 @@ +using CSV +using DataFrames +using PyPlot +rc("font", family="Arial", size=16.0) + + +final_field = CSV.read("field_final.csv", DataFrame)#, datarow = 2, type=Float64) + +x = convert(Array,final_field[:,1]) + +u_e = convert(Array,final_field[:,2]) +u_n = convert(Array,final_field[:,3]) +u_error = convert(Array,final_field[:,4]) + +u = Array{Float64}(undef, length(u_e), 2) +u[:,1] = u_e +u[:,2] = u_n + +for i = 1:Int64(length(u_error)) + u_error[i] = abs(u_error[i]) +end + +fig = figure("FTCS", figsize=(14,6)); +ax1 = fig[:add_subplot](1,2,1); +ax2 = fig[:add_subplot](1,2,2); + +ax1.plot(x, u_e, lw=4, ls = "-", color="b", label="Exact solution") +ax1.plot(x, u_n, lw=4, ls = "--", color="r", label="FTCS solution") +ax1.set_xlabel("\$x\$") +ax1.set_ylabel("\$u\$") +ax1.set_title("Solution field") +ax1.set_xlim(-1,1) +ax1.legend(fontsize=14, loc=0) + +ax2.plot(x, u_error, marker = "o", markeredgecolor="k", + markersize=8, color="g", lw=4) +ax2.set_xlabel("\$x\$") +ax2.set_ylabel("\$ϵ\$") +ax2.set_title("Discretization error") +ax2.set_xlim(-1,1) +#ax2.legend(fontsize=14, loc=0) + +#plt[:subplot](ax1); +#plt[:subplot](ax2); + +fig.tight_layout() +fig.savefig("ftcs.pdf") + +show() diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/README.txt b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/heat1dni81.cgns b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/heat1dni81.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/heat1dni81.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/main.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/main.cpp new file mode 100644 index 00000000..774700bb --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01/main.cpp @@ -0,0 +1,268 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename, Grid * grid ); + +class Grid +{ +public: + std::vector x; +}; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void solve() + { + std::cout << "solve()\n"; + Grid grid; + ReadCgnsGrid( "../heat1dni81.cgns", &grid ); + int ni = grid.x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid.x; + double dx = x[ 1 ] - x[ 0 ]; + //double dt = 0.0025; + double dt = dx / 10.0; + double t = 1.0; + int nt = std::round( t / dt ); + + std::cout << "dt = " << dt << "\n"; + std::cout << "t = " << t << "\n"; + std::cout << "nt = " << nt << "\n"; + std::cout << "ni = " << ni << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + + double alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + double beta = alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << beta << "\n"; + + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + + //compute L2 norm of the error + std::vector u_error( ni ); + //icount = 0; + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + int kkk = 1; + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +void ReadCgnsGrid( const std::string & filename, Grid * grid ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + //if( (i+1)%5 == 0 ) std::cout << "\n"; + } + //std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/README.txt b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/heat1d1blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/heat1d1blocksv1.cgns new file mode 100644 index 00000000..a367704f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/heat1d1blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/main.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/main.cpp new file mode 100644 index 00000000..3078dc74 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01a/main.cpp @@ -0,0 +1,269 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename, Grid * grid ); + +class Grid +{ +public: + std::vector x; +}; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void solve() + { + std::cout << "solve()\n"; + Grid grid; + //ReadCgnsGrid( "../heat1dni81.cgns", &grid ); + ReadCgnsGrid( "../heat1d1blocksv1.cgns", &grid ); + int ni = grid.x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid.x; + double dx = x[ 1 ] - x[ 0 ]; + //double dt = 0.0025; + double dt = dx / 10.0; + double t = 1.0; + int nt = std::round( t / dt ); + + std::cout << "dt = " << dt << "\n"; + std::cout << "t = " << t << "\n"; + std::cout << "nt = " << nt << "\n"; + std::cout << "ni = " << ni << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + + double alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + double beta = alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << beta << "\n"; + + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + + //compute L2 norm of the error + std::vector u_error( ni ); + //icount = 0; + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + int kkk = 1; + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +void ReadCgnsGrid( const std::string & filename, Grid * grid ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + //if( (i+1)%5 == 0 ) std::cout << "\n"; + } + //std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/CMakeLists.txt b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/CMakeLists.txt new file mode 100644 index 00000000..bfdbab14 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/README.txt b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/heat1d1blocksv1.cgns b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/heat1d1blocksv1.cgns new file mode 100644 index 00000000..a367704f Binary files /dev/null and b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/heat1d1blocksv1.cgns differ diff --git a/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/main.cpp b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/main.cpp new file mode 100644 index 00000000..25ce7e72 --- /dev/null +++ b/example/1d-heat-equation/ftcs/cpp/single_block/compare/01b/main.cpp @@ -0,0 +1,273 @@ +#include "cgnslib.h" +#include +#include +#include +#include +#include +#include + +class Grid; +void ReadCgnsGrid( const std::string & filename, Grid * grid ); + +class Grid +{ +public: + std::vector x; +}; + +class Solver +{ +public: + std::vector u_e; + std::vector u,un; + std::vector error; +public: + void solve() + { + std::cout << "solve()\n"; + Grid grid; + ReadCgnsGrid( "../heat1d1blocksv1.cgns", &grid ); + int ni = grid.x.size(); + std::cout << "ni = " << ni << "\n"; + + std::vector & x = grid.x; + double dx = x[ 1 ] - x[ 0 ]; + //double dt = 0.0025; + double dt = dx / 10.0; + double t = 1.0; + int nt = std::round( t / dt ); + //int nt = 1; + + double total_time = nt * dt; + + std::cout << "dt = " << dt << "\n"; + std::cout << "t = " << t << "\n"; + std::cout << "nt = " << nt << "\n"; + std::cout << "ni = " << ni << "\n"; + std::cout << "total_time = " << total_time << "\n"; + + u_e.resize( ni ); + u.resize( ni ); + un.resize( ni ); + + for ( int i = 0; i < ni; ++ i ) + { + //u_e[ i ] = - std::exp( -t ) * std::sin( std::numbers::pi * x[i] ); //theory solution + u_e[ i ] = - std::exp( -total_time ) * std::sin( std::numbers::pi * x[i] ); //theory solution + un[ i ] = - std::sin( std::numbers::pi * x[ i ] ); //initial condition @ t=0 + } + un[ 0 ] = 0.0; + un[ ni - 1 ] = 0.0; + + double alpha = 1 / ( std::numbers::pi * std::numbers::pi ); + double beta = alpha * dt / ( dx * dx ); + std::cout << "alpha = " << std::setprecision(15) << alpha << "\n"; + std::cout << "beta = " << std::setprecision(15) << beta << "\n"; + + for ( int it = 0; it < nt; ++ it ) + { + for ( int i = 1; i < ni - 1; ++ i ) + { + u[ i ] = un[ i ] + beta * ( un[ i + 1 ] - 2.0 * un[ i ] + un[ i - 1 ] ); + } + //boundary + u[ 0 ] = 0.0; // boundary condition at x = -1 + u[ ni - 1 ] = 0.0; // boundary condition at x = 1 + this->update( un, u ); + } + + //compute L2 norm of the error + std::vector u_error( ni ); + //icount = 0; + for ( int i = 0; i < ni; ++ i ) + { + u_error[ i ] = un[ i ] - u_e[ i ]; + } + + double rms_error = compute_l2norm( ni, u_error ); + double max_error = compute_max_error( ni, u_error ); + std::cout << "max_error = " << std::setprecision(15) << max_error << "\n"; + //create output file for L2-norm + std::fstream file; + file.open("output.txt", std::fstream::out); + std::format_to(std::ostream_iterator(file), "Error details: \n"); + std::format_to(std::ostream_iterator(file), "L-2 Norm = {0}\n", rms_error); + std::format_to(std::ostream_iterator(file), "Maximum Norm = {0}\n", max_error); + file.close(); + int kkk = 1; + } + + void update( std::vector &un, std::vector &u ) + { + for ( int i = 0; i < u.size(); ++ i ) + { + un[ i ] = u[ i ]; + } + } + + double compute_l2norm( int ni, std::vector & r ) + { + double rms = 0.0; + for ( int i = 1; i < ni - 1; ++ i ) + { + rms += r[ i ] * r[ i ]; + } + rms = std::sqrt( rms / ( ni - 2 ) ); + return rms; + } + + double compute_max_error( int ni, std::vector & u_error ) + { + double val_max = -1; + int ipos = -1; + for ( int i = 1; i < ni - 1; ++ i ) + { + //val_max = std::max( val_max, std::abs( u_error[ i ] ) ); + if ( val_max < std::abs( u_error[ i ] ) ) + { + ipos = i; + val_max = std::abs( u_error[ i ] ); + } + } + std::cout << " ipos = " << ipos << "\n"; + return val_max; + } +}; + +void ReadCgnsGrid( const std::string & filename, Grid * grid ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + //std::vector coord( nNodes ); + std::vector coord( nNodes * sizeof(double) ); + grid->x.resize( nNodes ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < nNodes; ++ i ) + { + //std::cout << xd[i] << " "; + grid->x[ i ] = xd[ i ]; + //if( (i+1)%5 == 0 ) std::cout << "\n"; + } + //std::cout << "\n"; + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + } + } + } + cg_close(fileId); +} + +int main(int argc, char **argv) +{ + Solver solver; + solver.solve(); + return 0; +} diff --git a/example/1d-heat-equation/ftcs/fft.ipynb b/example/1d-heat-equation/ftcs/python/fft.ipynb similarity index 100% rename from example/1d-heat-equation/ftcs/fft.ipynb rename to example/1d-heat-equation/ftcs/python/fft.ipynb diff --git a/example/1d-heat-equation/ftcs/ftcs.py b/example/1d-heat-equation/ftcs/python/ftcs.py similarity index 65% rename from example/1d-heat-equation/ftcs/ftcs.py rename to example/1d-heat-equation/ftcs/python/ftcs.py index f9b80031..10819ad7 100644 --- a/example/1d-heat-equation/ftcs/ftcs.py +++ b/example/1d-heat-equation/ftcs/python/ftcs.py @@ -10,6 +10,16 @@ def compute_l2norm(nx,r): rms += r[i] * r[i] rms = np.sqrt( rms / ( ( nx - 1 ) ) ) return rms + +def compute_max_error( nx, u_error ): + val_max = -1; + ipos = -1; + for i in range(1, nx): + if ( val_max < np.abs( u_error[ i ] ) ): + ipos = i; + val_max = np.abs( u_error[ i ] ) + print( " ipos = ", ipos ) + return val_max; x_l = -1.0 x_r = 1.0 @@ -21,6 +31,7 @@ def compute_l2norm(nx,r): dt = 0.0025 t = 1.0 nt = int( t / dt ) +#nt = 1 print( " nt = ", nt ) alpha = 1 / ( np.pi**2 ) @@ -39,16 +50,57 @@ def compute_l2norm(nx,r): un[0,0 ] = 0.0 un[0,nx] = 0.0 +icount = 0 +for i in range(0, nx+1): + print("{0:.15f}".format(un[0,i]), end = " ") + icount += 1 + if( icount % 5 == 0 ): + print("") +print() +print() + beta = alpha * dt / ( dx**2 ) +print(" alpha ={0:.15f}".format(alpha)) +print(" beta ={0:.15f}".format(beta)) + for k in range(1, nt+1): for i in range(1, nx): un[k,i] = un[k-1,i] + beta * ( un[k-1,i+1] - 2.0 * un[k-1,i] + un[k-1,i-1] ) un[k,0 ] = 0.0 # boundary condition at x = -1 un[k,nx] = 0.0 # boundary condition at x = 1 + +icount = 0 +for i in range(0, nx+1): + print("{0:.15f}".format(un[1,i]), end = " ") + icount += 1 + if( icount % 5 == 0 ): + print("") +print() +print() # compute L2 norm of the error u_error = un[nt,:] - u_e +icount = 0 +for i in range(0, nx+1): + print("{0:.15f}".format(u_error[i]), end = " ") + #print(u_error[i], " ") + icount += 1 + if( icount % 5 == 0 ): + print("") +print() +print() + +icount = 0 +for i in range(0, nx+1): + print("{0:.15f}".format(u_e[i]), end = " ") + icount += 1 + if( icount % 5 == 0 ): + print("") + +my_max_error = compute_max_error( nx, u_error ) +print("my_max_error = {0:.15f}".format(my_max_error)) + rms_error = compute_l2norm(nx,u_error) max_error = np.max( np.abs(u_error) ) @@ -77,4 +129,4 @@ def compute_l2norm(nx,r): plt.tight_layout() plt.ticklabel_format(axis='y', style='sci', scilimits=(-4,-4)) -plt.show(); \ No newline at end of file +plt.show(); diff --git a/example/1d-heat-equation/ftcs/python/output.txt b/example/1d-heat-equation/ftcs/python/output.txt new file mode 100644 index 00000000..77c008ea --- /dev/null +++ b/example/1d-heat-equation/ftcs/python/output.txt @@ -0,0 +1,3 @@ +Error details: +L-2 Norm = 0.00019281858911820367 +Maximum Norm = 0.0002709770126991251 diff --git a/example/1d-heat-equation/grid/01/CMakeLists.txt b/example/1d-heat-equation/grid/01/CMakeLists.txt new file mode 100644 index 00000000..ec3f9fb1 --- /dev/null +++ b/example/1d-heat-equation/grid/01/CMakeLists.txt @@ -0,0 +1,70 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +#list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_14 ) + +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/1d-heat-equation/grid/01/main.cpp b/example/1d-heat-equation/grid/01/main.cpp new file mode 100644 index 00000000..f5f778be --- /dev/null +++ b/example/1d-heat-equation/grid/01/main.cpp @@ -0,0 +1,78 @@ +#include "cgnslib.h" +#include +#include + +void write_grid_str(); +//void write_con2zn_str(); + +void write_grid_str() +{ + const int ni = 101; + double x[ni]; + cgsize_t isize[9]; + int index_file,icelldim,iphysdim,index_base; + int index_zone,index_coord; + char basename[33],zonename[33]; + cgsize_t ipnts[ 2 ]; + int ilo,ihi; + + double x_l = -1.0; + double x_r = 1.0; + + double dx = ( x_r - x_l ) / ( ni - 1 ); + + /* create gridpoints for simple example: */ + for ( int i = 0; i < ni; ++ i ) + { + x[ i ] = x_l + i * dx; + } + + if (cg_open("heat1d.cgns",CG_MODE_WRITE,&index_file)) cg_error_exit(); + + strcpy(basename,"Base"); + icelldim=1; + iphysdim=3; + cg_base_write(index_file,basename,icelldim,iphysdim,&index_base); + /* vertex size */ + isize[0]=ni; + /* cell size */ + isize[1]=ni-1; + /* boundary vertex size (always zero for structured grids) */ + isize[2]=0; + isize[3]=0; + isize[4]=0; + isize[5]=0; + isize[6]=0; + isize[7]=0; + isize[8]=0; + + ilo=1; + ihi=isize[0]; + strcpy(zonename,"Zone 1"); + cg_zone_write(index_file,index_base,zonename,isize,CGNS_ENUMV(Structured),&index_zone); + cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"x",x,&index_coord); + + /* lower point of range */ + ipnts[0]=ilo; + /* upper point of range */ + ipnts[1]=ilo; + + int index_bc = -1; + cg_boco_write(index_file,index_base,index_zone,"L",CGNS_ENUMV(BCInflow),CGNS_ENUMV(PointRange),2,ipnts,&index_bc); + + /* lower point of range */ + ipnts[0]=ihi; + /* upper point of range */ + ipnts[1]=ihi; + + cg_boco_write(index_file,index_base,index_zone,"R",CGNS_ENUMV(BCOutflow),CGNS_ENUMV(PointRange),2,ipnts,&index_bc); + + cg_close(index_file); +} + +int main(int argc, char **argv) +{ + write_grid_str(); + return 0; +} + diff --git a/example/partition/struct/1d/01/CMakeLists.txt b/example/partition/struct/1d/01/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/1d/01/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/01/CgnsGrid.cpp b/example/partition/struct/1d/01/CgnsGrid.cpp new file mode 100644 index 00000000..055545c4 --- /dev/null +++ b/example/partition/struct/1d/01/CgnsGrid.cpp @@ -0,0 +1,217 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +std::vector Global::zones; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + //grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} \ No newline at end of file diff --git a/example/partition/struct/1d/01/CgnsGrid.h b/example/partition/struct/1d/01/CgnsGrid.h new file mode 100644 index 00000000..72c47bb8 --- /dev/null +++ b/example/partition/struct/1d/01/CgnsGrid.h @@ -0,0 +1,62 @@ +#pragma once +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBc +{ +public: +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static std::vector zones; + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); diff --git a/example/partition/struct/1d/01/Partition.cpp b/example/partition/struct/1d/01/Partition.cpp new file mode 100644 index 00000000..2977d8a1 --- /dev/null +++ b/example/partition/struct/1d/01/Partition.cpp @@ -0,0 +1,636 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +DimInfo::DimInfo() +{ + this->dim = 1; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo::~DimInfo() +{ +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +SplitZone::SplitZone() +{ + ; +} + +SplitZone::~SplitZone() +{ + ; +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL = new SplitZone(); + zoneL->SetParent( this ); + + zoneR = new SplitZone(); + zoneR->SetParent( this ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + //zoneL->CreateBc(); + //zoneR->CreateBc(); + + //CreateInterfaceBc( zoneL, zoneR ); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + ; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGrid( "../heat1dni81.cgns" ); + + this->nOriZone = ::Global::zones.size(); + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + refZone[ iZone ] = new SplitZone(); + refZone[ iZone ]->SetZoneIndex( iZone ); + refZone[ iZone ]->oriZoneId = iZone; + refZone[ iZone ]->SetProcId( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + //HXVector< ZoneBc * > & bcList = splitZone->GetZoneBcList(); + //bcList.resize( nBcRegion ); + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + } + + //splitZone->NormalizeBc(); + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + //this->SetZoneIndex(); +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNode = 3 * 3 * 2; +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = 0; + SplitZone * zoneR = 0; + + zone->Split( zoneL, zoneR, nCell ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + this->RemoveZoneFromUnsignedGroup( zone ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNode && nTarget > this->minNode ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::DumpPartitionedGridFile() +{ + int fileId = -1; + std::string filename = "split1d.cgns"; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId); + std::cout << "fileId = " << fileId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = 1; + int iphysdim = 1; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3, 0 ); + for ( int i = 0; i < index_dim; ++ i ) + { + isize[ i ] = splitZone->dimInfo.dimList[ i ]; + } + for ( int i = 0; i < index_dim; ++ i ) + { + int ii = index_dim * 1; + isize[ ii + i ] = splitZone->dimInfo.dimList[ i ] - 1; + } + for ( int i = 0; i < index_dim; ++ i ) + { + int ii = index_dim * 2; + isize[ ii + i ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + int zoneId = -1; + + std::string zonename = "B" + std::to_string( iProc ) + "Zone" + std::to_string( iZone ); + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + int ncoords = 1; + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType = RealDouble; + std::string coordname = "X"; + //cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), const void * coord_ptr, &coorId ); + // + // + + // + //char coordname[33]; + //cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + //std::cout << "coordname = " << coordname << "\n"; + //std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + ////std::vector coord( nNodes ); + //std::vector coord( nNodes * sizeof(double) ); + //grid->x.resize( nNodes ); + + //cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coord.data() ); + //double * xd = reinterpret_cast(const_cast(coord.data())); + //for ( int i = 0; i < nNodes; ++ i ) + //{ + // //std::cout << coord[i] << " "; + // std::cout << xd[i] << " "; + // grid->x[ i ] = xd[ i ]; + // if( (i+1)%5 == 0 ) std::cout << "\n"; + //} + //std::cout << "\n"; + } + + //int nbocos = -1; + + //cg_nbocos( fileId, baseId, zoneId, &nbocos ); + //std::cout << "nbocos = " << nbocos << "\n"; + //for ( int iboco = 0; iboco < nbocos; ++ iboco ) + //{ + // int bccoId = iboco + 1; + // GridLocation_t location; + // cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + // std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + // ZoneBc * zonebc = new ZoneBc(); + // zone->bccos.push_back( zonebc ); + + // char boconame[ 33 ]; + // BCType_t bocotype; + // PointSetType_t ptset_type; + // cgsize_t npnts = 0; + // std::vector normalIndex(index_dim,-1); + // cgsize_t normalListSize = 0; + // DataType_t normalDataType; + // int ndataset = -1; + + // cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + // &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + // std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + // std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + // std::cout << "npnts = " << npnts << "\n"; + // std::cout << "normalIndex = "; + // for ( int i = 0; i < index_dim; ++ i ) + // { + // std::cout << normalIndex[i] << " "; + // } + // std::cout << "\n"; + // std::cout << "normalListSize = " << normalListSize << "\n"; + // std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + // std::cout << "ndataset = " << ndataset << "\n"; + + // std::vector normalList(nNodes*iphysdim*sizeof(double)); + + // std::vector pnts(npnts*index_dim); + // cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + // std::cout << "pnts = "; + // for ( int i = 0; i < pnts.size(); ++ i ) + // { + // std::cout << pnts[ i ] << " "; + // } + // std::cout << "\n"; + + // double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + // //std::cout << "normalList = "; + // //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + // //{ + // // std::cout << normal_d[ i ] << " "; + // //} + // //std::cout << "\n"; + //} + } + } + cg_close(fileId); +} \ No newline at end of file diff --git a/example/partition/struct/1d/01/Partition.h b/example/partition/struct/1d/01/Partition.h new file mode 100644 index 00000000..c15e8bf5 --- /dev/null +++ b/example/partition/struct/1d/01/Partition.h @@ -0,0 +1,93 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int oriZoneId; +protected: + SplitZone * parent; +public: + int GetNCell(); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + double minNode; + int nTZone; + int nOriZone; + int nProc; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/01/README.txt b/example/partition/struct/1d/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/01/heat1dni81.cgns b/example/partition/struct/1d/01/heat1dni81.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/partition/struct/1d/01/heat1dni81.cgns differ diff --git a/example/partition/struct/1d/01/main.cpp b/example/partition/struct/1d/01/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/01/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/01a/CMakeLists.txt b/example/partition/struct/1d/01a/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/1d/01a/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/01a/CgnsGrid.cpp b/example/partition/struct/1d/01a/CgnsGrid.cpp new file mode 100644 index 00000000..055545c4 --- /dev/null +++ b/example/partition/struct/1d/01a/CgnsGrid.cpp @@ -0,0 +1,217 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +std::vector Global::zones; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + //grid->x.resize( nNodes ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} \ No newline at end of file diff --git a/example/partition/struct/1d/01a/CgnsGrid.h b/example/partition/struct/1d/01a/CgnsGrid.h new file mode 100644 index 00000000..72c47bb8 --- /dev/null +++ b/example/partition/struct/1d/01a/CgnsGrid.h @@ -0,0 +1,62 @@ +#pragma once +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBc +{ +public: +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static std::vector zones; + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); diff --git a/example/partition/struct/1d/01a/Partition.cpp b/example/partition/struct/1d/01a/Partition.cpp new file mode 100644 index 00000000..2af0e965 --- /dev/null +++ b/example/partition/struct/1d/01a/Partition.cpp @@ -0,0 +1,776 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +DimInfo::DimInfo() +{ + this->dim = 1; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo::~DimInfo() +{ +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +SplitZone::SplitZone() +{ + this->oriZoneId = -1; + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->oriZoneId = rootSplitZone->oriZoneId; + std::cout << "this->oriZoneId = " << this->oriZoneId << "\n"; + + this->dimInfo.ComputeRminmax( ref ); +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL = new SplitZone(); + zoneL->SetParent( this ); + + zoneR = new SplitZone(); + zoneR->SetParent( this ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + //zoneL->CreateBc(); + //zoneR->CreateBc(); + + //CreateInterfaceBc( zoneL, zoneR ); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + ; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGrid( "../heat1dni81.cgns" ); + + this->nOriZone = ::Global::zones.size(); + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + refZone[ iZone ] = new SplitZone(); + refZone[ iZone ]->SetZoneIndex( iZone ); + refZone[ iZone ]->oriZoneId = iZone; + refZone[ iZone ]->SetProcId( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + //HXVector< ZoneBc * > & bcList = splitZone->GetZoneBcList(); + //bcList.resize( nBcRegion ); + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + } + + //splitZone->NormalizeBc(); + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + //this->SetZoneIndex(); +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNode = 3 * 3 * 2; +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = 0; + SplitZone * zoneR = 0; + + zone->Split( zoneL, zoneR, nCell ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + this->RemoveZoneFromUnsignedGroup( zone ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNode && nTarget > this->minNode ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::DumpPartitionedGridFile() +{ + int fileId = -1; + std::string filename = "split1d.cgns"; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId); + std::cout << "fileId = " << fileId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = 1; + int iphysdim = 1; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "B" + std::to_string( iProc ) + "Zone" + std::to_string( iZone ); + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + } + std::cout << "nNodes = " << nNodes << "\n"; + + std::cout << "irmin, irmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << irmin[ m ] << " " << irmax[ m ] << "\n"; + } + + //std::vector ref( index_dim, 0 ); + + //SplitZone * rootSplitZone = 0; + //splitZone->GetRootInfo( rootSplitZone, ref ); + + //int oriZoneId = rootSplitZone->oriZoneId; + //std::cout << "oriZoneId = " << oriZoneId << "\n"; + splitZone->ComputeRminmax(); + + Zone * zone = Global::zones[ splitZone->oriZoneId ]; + + //std::vector rmin( index_dim ); + //std::vector rmax( index_dim ); + + //for ( int m = 0; m < index_dim; ++ m ) + //{ + // rmin[ m ] = ref[ m ] + 1; + // rmax[ m ] = ref[ m ] + splitZone->dimInfo.dimList[ m ]; + //} + + //std::cout << "rmin, rmax = \n"; + //for ( int m = 0; m < index_dim; ++ m ) + //{ + // std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + //} + + int ncoords = 1; + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = "X"; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord( nNodes * sizeof(double) ); + { + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = splitZone->dimInfo.dimList[ 0 ]; + int nj = splitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } + //for ( int i = 0; i < nNodes; ++ i ) + //{ + // int j = i + ref[ 0 ]; + // xlocal[ i ] = xglobal[j]; + // std::cout << xlocal[ i ] << " "; + // if ( ( i + 1 ) % 5 == 0 ) std::cout << "\n"; + //} + //std::cout << "\n"; + } + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "cg_get_error() = " << cg_get_error() << "\n"; + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + //int nbocos = -1; + + //cg_nbocos( fileId, baseId, zoneId, &nbocos ); + //std::cout << "nbocos = " << nbocos << "\n"; + //for ( int iboco = 0; iboco < nbocos; ++ iboco ) + //{ + // int bccoId = iboco + 1; + // GridLocation_t location; + // cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + // std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + // ZoneBc * zonebc = new ZoneBc(); + // zone->bccos.push_back( zonebc ); + + // char boconame[ 33 ]; + // BCType_t bocotype; + // PointSetType_t ptset_type; + // cgsize_t npnts = 0; + // std::vector normalIndex(index_dim,-1); + // cgsize_t normalListSize = 0; + // DataType_t normalDataType; + // int ndataset = -1; + + // cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + // &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + // std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + // std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + // std::cout << "npnts = " << npnts << "\n"; + // std::cout << "normalIndex = "; + // for ( int i = 0; i < index_dim; ++ i ) + // { + // std::cout << normalIndex[i] << " "; + // } + // std::cout << "\n"; + // std::cout << "normalListSize = " << normalListSize << "\n"; + // std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + // std::cout << "ndataset = " << ndataset << "\n"; + + // std::vector normalList(nNodes*iphysdim*sizeof(double)); + + // std::vector pnts(npnts*index_dim); + // cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + // std::cout << "pnts = "; + // for ( int i = 0; i < pnts.size(); ++ i ) + // { + // std::cout << pnts[ i ] << " "; + // } + // std::cout << "\n"; + + // double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + // //std::cout << "normalList = "; + // //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + // //{ + // // std::cout << normal_d[ i ] << " "; + // //} + // //std::cout << "\n"; + //} + } + } + cg_close(fileId); +} \ No newline at end of file diff --git a/example/partition/struct/1d/01a/Partition.h b/example/partition/struct/1d/01a/Partition.h new file mode 100644 index 00000000..2c2052cf --- /dev/null +++ b/example/partition/struct/1d/01a/Partition.h @@ -0,0 +1,101 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int oriZoneId; +protected: + SplitZone * parent; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + double minNode; + int nTZone; + int nOriZone; + int nProc; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/01a/README.txt b/example/partition/struct/1d/01a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/01a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/01a/heat1dni81.cgns b/example/partition/struct/1d/01a/heat1dni81.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/partition/struct/1d/01a/heat1dni81.cgns differ diff --git a/example/partition/struct/1d/01a/main.cpp b/example/partition/struct/1d/01a/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/01a/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/01b/CMakeLists.txt b/example/partition/struct/1d/01b/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/1d/01b/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/01b/CgnsGrid.cpp b/example/partition/struct/1d/01b/CgnsGrid.cpp new file mode 100644 index 00000000..ff8aa2f8 --- /dev/null +++ b/example/partition/struct/1d/01b/CgnsGrid.cpp @@ -0,0 +1,227 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +std::vector Global::zones; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} \ No newline at end of file diff --git a/example/partition/struct/1d/01b/CgnsGrid.h b/example/partition/struct/1d/01b/CgnsGrid.h new file mode 100644 index 00000000..12e7bb21 --- /dev/null +++ b/example/partition/struct/1d/01b/CgnsGrid.h @@ -0,0 +1,67 @@ +#pragma once +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + std::vector pnts; +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static std::vector zones; + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); diff --git a/example/partition/struct/1d/01b/Partition.cpp b/example/partition/struct/1d/01b/Partition.cpp new file mode 100644 index 00000000..6ca6dfad --- /dev/null +++ b/example/partition/struct/1d/01b/Partition.cpp @@ -0,0 +1,970 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->dim = 1; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo::~DimInfo() +{ +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + this->regionAxis = rhs.regionAxis; + + return * this; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } + this->ComputeRegionAxis(); +} + +int RangeRegion::ComputeRegionAxis() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] == this->end[ m ] ) + { + this->regionAxis = m; + return this->regionAxis; + } + } + return this->regionAxis; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + overlapRegion.start[ m ] = std::max( region1.start[ m ], region2.start[ m ] ); + overlapRegion.end [ m ] = std::min( region1.end [ m ], region2.end [ m ] ); + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +SplitBc * CreateSplitBc( RangeRegion & bcRegion, RangeRegion & zoneDomainRegion ) +{ + int sRegionAxis = bcRegion.ComputeRegionAxis(); + int tRegionAxis = zoneDomainRegion.ComputeRegionAxis(); + + //Two regions in different directions + if ( sRegionAxis != tRegionAxis ) + { + return 0; + } + + //Although the two regions are in the same direction, the coordinates are inconsistent. + if ( bcRegion.start[ sRegionAxis ] != zoneDomainRegion.start[ sRegionAxis ] ) + { + return 0; + } + + RangeRegion overlapRegion; + ComputeOverlapRegion( bcRegion, zoneDomainRegion, overlapRegion ); + + if ( CheckOverLapping( overlapRegion ) ) + { + SplitBc * splitBc = new SplitBc(); + splitBc->SetRegion( overlapRegion ); + return splitBc; + } + + int kkk = 1; + + return 0; +} + + +SplitBc::SplitBc() +{ +} + +SplitBc::~SplitBc() +{ +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::SetZoneBcFromParentBc( SplitBc * parentSplitBc ) +{ + this->bcType = parentSplitBc->bcType; + //this->LocalCoordinate(); + this->region.regionAxis = parentSplitBc->region.regionAxis; + this->InheritPatchBc( parentSplitBc ); +} + +void SplitBc::InheritPatchBc( SplitBc * parentSplitBc ) +{ + if ( ! ( this->bcType < 0 ) ) return; + + this->patch = new SplitBcPatch(); + + this->patch->splitZone = parentSplitBc->patch->splitZone; + this->patch->faceAxis = parentSplitBc->patch->faceAxis; + +} + +SplitBcPatch::SplitBcPatch() +{ +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +SplitZone::SplitZone() +{ + this->oriZoneId = -1; + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->oriZoneId = rootSplitZone->oriZoneId; + std::cout << "this->oriZoneId = " << this->oriZoneId << "\n"; + + this->dimInfo.ComputeRminmax( ref ); +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL = new SplitZone(); + zoneL->SetParent( this ); + + zoneR = new SplitZone(); + zoneR->SetParent( this ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + //CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + std::vector< SplitBc * > & parentSplitBcList = this->parent->GetSplitBcList(); + + int nParentSplitBcs = parentSplitBcList.size(); + + for ( int iParentBc = 0; iParentBc < nParentSplitBcs; ++ iParentBc ) + { + SplitBc * parentSplitBc = parentSplitBcList[ iParentBc ]; + + this->CreateSplitBc( parentSplitBc ); + } +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + //splitBc->LocalCoordinate(); + //splitBc->CreatePatchBc( parentSplitBc ); + + int kkk = 1; + } + } + //else + //{ + // int nChild = parentBc->GetChild()->size(); + // for ( int iChild = 0; iChild < nChild; ++ iChild ) + // { + // this->CreateBc( ( * parentBc->GetChild() )[ iChild ] ); + // } + //} +} + + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + ; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGrid( "../heat1dni81.cgns" ); + + this->nOriZone = ::Global::zones.size(); + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + refZone[ iZone ] = new SplitZone(); + refZone[ iZone ]->SetZoneIndex( iZone ); + refZone[ iZone ]->oriZoneId = iZone; + refZone[ iZone ]->SetProcId( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + SplitBc * splitBc = new SplitBc(); + splitBcList.push_back( splitBc ); + + ZoneBc * zoneBc = zone->bccos[ iBcRegion ]; + + splitBc->splitZone = splitZone; + splitBc->bcType = zoneBc->bcType; + splitBc->SetRegion( zoneBc->pnts ); + } + + int kkk = 1; + + //splitZone->NormalizeBc(); + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + //this->SetZoneIndex(); +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNode = 3 * 3 * 2; +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = 0; + SplitZone * zoneR = 0; + + zone->Split( zoneL, zoneR, nCell ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + this->RemoveZoneFromUnsignedGroup( zone ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNode && nTarget > this->minNode ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + Zone * zone = Global::zones[ splitZone->oriZoneId ]; + SplitZone * rootSplitZone = this->refZone[ splitZone->oriZoneId ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + int fileId = -1; + std::string filename = "split1d.cgns"; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId); + std::cout << "fileId = " << fileId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = 1; + int iphysdim = 1; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "B" + std::to_string( iProc ) + "Zone" + std::to_string( iZone ); + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + Zone * zone = Global::zones[ splitZone->oriZoneId ]; + SplitZone * rootSplitZone = this->refZone[ splitZone->oriZoneId ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = "X"; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "cg_get_error() = " << cg_get_error() << "\n"; + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector bccos; + + //this->DumpBc( splitZone ); + + int nbocos = splitZone->splitBcList.size(); + + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = splitZone->splitBcList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId); + } + } + } + cg_close(fileId); +} \ No newline at end of file diff --git a/example/partition/struct/1d/01b/Partition.h b/example/partition/struct/1d/01b/Partition.h new file mode 100644 index 00000000..cc2bb13f --- /dev/null +++ b/example/partition/struct/1d/01b/Partition.h @@ -0,0 +1,164 @@ +#pragma once +#include +#include +#include + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneBox( RangeRegion & zoneBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + int regionAxis = -1; + std::vector start; + std::vector end; +public: + RangeRegion & operator = ( const RangeRegion & rhs ); + void SetRegion( std::vector &pnts ); + int ComputeRegionAxis(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); +public: + void SetZoneBcFromParentBc( SplitBc * parentSplitBc ); + void InheritPatchBc( SplitBc * parentSplitBc ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + int faceAxis; +public: + SplitZone * splitZone; +}; + + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int oriZoneId; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + void CreateBcFromParent(); + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + double minNode; + int nTZone; + int nOriZone; + int nProc; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/01b/README.txt b/example/partition/struct/1d/01b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/01b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/01b/heat1dni81.cgns b/example/partition/struct/1d/01b/heat1dni81.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/partition/struct/1d/01b/heat1dni81.cgns differ diff --git a/example/partition/struct/1d/01b/main.cpp b/example/partition/struct/1d/01b/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/01b/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/01c/CMakeLists.txt b/example/partition/struct/1d/01c/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/1d/01c/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/01c/CgnsGrid.cpp b/example/partition/struct/1d/01c/CgnsGrid.cpp new file mode 100644 index 00000000..e58aa1ec --- /dev/null +++ b/example/partition/struct/1d/01c/CgnsGrid.cpp @@ -0,0 +1,231 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +std::vector Global::zones; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} \ No newline at end of file diff --git a/example/partition/struct/1d/01c/CgnsGrid.h b/example/partition/struct/1d/01c/CgnsGrid.h new file mode 100644 index 00000000..b84abd1d --- /dev/null +++ b/example/partition/struct/1d/01c/CgnsGrid.h @@ -0,0 +1,69 @@ +#pragma once +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + std::vector pnts; +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static std::vector zones; + static void FreeData(); + static int cell_dim; + static int phys_dim; +}; + +void ReadCgnsGrid( const std::string & filename ); diff --git a/example/partition/struct/1d/01c/Partition.cpp b/example/partition/struct/1d/01c/Partition.cpp new file mode 100644 index 00000000..5011f918 --- /dev/null +++ b/example/partition/struct/1d/01c/Partition.cpp @@ -0,0 +1,1248 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->dim = 1; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo::~DimInfo() +{ +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + this->regionAxis = rhs.regionAxis; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } + this->ComputeRegionAxis(); +} + +int RangeRegion::ComputeRegionAxis() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] == this->end[ m ] ) + { + this->regionAxis = m; + return this->regionAxis; + } + } + return this->regionAxis; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + overlapRegion.start[ m ] = std::max( region1.start[ m ], region2.start[ m ] ); + overlapRegion.end [ m ] = std::min( region1.end [ m ], region2.end [ m ] ); + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +SplitBc * CreateSplitBc( RangeRegion & bcRegion, RangeRegion & zoneDomainRegion ) +{ + int sRegionAxis = bcRegion.ComputeRegionAxis(); + int tRegionAxis = zoneDomainRegion.ComputeRegionAxis(); + + //Two regions in different directions + if ( sRegionAxis != tRegionAxis ) + { + return 0; + } + + //Although the two regions are in the same direction, the coordinates are inconsistent. + if ( bcRegion.start[ sRegionAxis ] != zoneDomainRegion.start[ sRegionAxis ] ) + { + return 0; + } + + RangeRegion overlapRegion; + ComputeOverlapRegion( bcRegion, zoneDomainRegion, overlapRegion ); + + if ( CheckOverLapping( overlapRegion ) ) + { + SplitBc * splitBc = new SplitBc(); + splitBc->SetRegion( overlapRegion ); + return splitBc; + } + + int kkk = 1; + + return 0; +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + int kkk = 1; + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + SplitBc * splitBcL = new SplitBc(); + zoneL->AddSplitBc( splitBcL ); + + SplitBc * splitBcR = new SplitBc(); + zoneR->AddSplitBc( splitBcR ); + + splitBcL->splitZone = zoneL; + splitBcL->SetRegion( localInterfaceRegionL ); + splitBcL->bcType = BCTypeUserDefined; + + splitBcR->splitZone = zoneR; + splitBcR->SetRegion( localInterfaceRegionR ); + splitBcR->bcType = BCTypeUserDefined; + + //localInterfaceRegionL.MarkPatchBc(); + //localInterfaceRegionR.MarkPatchBc(); + + SplitBcPatch * splitBcPatchL = new SplitBcPatch(); + splitBcL->patch = splitBcPatchL; + splitBcPatchL->region = localInterfaceRegionR; + splitBcPatchL->splitZone = zoneR; + + SplitBcPatch * splitBcPatchR = new SplitBcPatch(); + splitBcR->patch = splitBcPatchR; + splitBcPatchR->region = localInterfaceRegionL; + splitBcPatchR->splitZone = zoneL; + + //splitBcL->Normalize(); + //splitBcR->Normalize(); +} + + +SplitBc::SplitBc() +{ +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::SetZoneBcFromParentBc( SplitBc * parentSplitBc ) +{ + this->bcType = parentSplitBc->bcType; + //this->LocalCoordinate(); + this->region.regionAxis = parentSplitBc->region.regionAxis; + this->InheritPatchBc( parentSplitBc ); +} + +void SplitBc::InheritPatchBc( SplitBc * parentSplitBc ) +{ + if ( ! ( this->bcType < 0 ) ) return; + + this->patch = new SplitBcPatch(); + + this->patch->splitZone = parentSplitBc->patch->splitZone; + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildPatchBc( tRangeBox, this->splitZone ); +} + +SplitBcPatch::SplitBcPatch() +{ +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL = new SplitZone(); + zoneL->SetParent( this ); + + zoneR = new SplitZone(); + zoneR->SetParent( this ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + std::vector< SplitBc * > & parentSplitBcList = this->parent->GetSplitBcList(); + + int nParentSplitBcs = parentSplitBcList.size(); + + for ( int iParentBc = 0; iParentBc < nParentSplitBcs; ++ iParentBc ) + { + SplitBc * parentSplitBc = parentSplitBcList[ iParentBc ]; + + this->CreateSplitBc( parentSplitBc ); + } +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + splitBc->ChangeRegionToLocalCoordinate(); + //splitBc->CreatePatchBc( parentSplitBc ); + + int kkk = 1; + } + } + else + { + int nChilds = parentSplitBc->child->size(); + for ( int iChild = 0; iChild < nChilds; ++ iChild ) + { + this->CreateSplitBc( ( * parentSplitBc->child )[ iChild ] ); + } + } +} + + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + ; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + this->ReadGrid(); + this->Split(); + this->ModifyZoneIndex(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGrid( "../heat1dni81.cgns" ); + + this->nOriZone = ::Global::zones.size(); + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + SplitBc * splitBc = new SplitBc(); + splitBcList.push_back( splitBc ); + + ZoneBc * zoneBc = zone->bccos[ iBcRegion ]; + + splitBc->splitZone = splitZone; + splitBc->bcType = zoneBc->bcType; + splitBc->SetRegion( zoneBc->pnts ); + } + + int kkk = 1; + + //splitZone->NormalizeBc(); + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + //this->SetZoneIndex(); +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + int index_dim = Global::cell_dim; + this->minNode = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + this->minNode *= 2; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = 0; + SplitZone * zoneR = 0; + + zone->Split( zoneL, zoneR, nCell ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + this->RemoveZoneFromUnsignedGroup( zone ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNode && nTarget > this->minNode ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ + //std::vector< ZoneBc * > leafZoneBc; + + //std::vector< ZoneBc * > & zoneBcList = splitZone->GetZoneBcList(); + + //for ( int i = 0; i < zoneBcList.size(); ++ i ) + //{ + // std::vector< ZoneBc * > cl = zoneBcList[ i ]->GetLeaves(); + // for ( int j = 0; j < cl.size(); ++ j ) + // { + // leafZoneBc.push_back( cl[ j ] ); + // } + //} + + //int nZoneBc = leafZoneBc.size(); + + //for ( int iZoneBc = 0; iZoneBc < nZoneBc; ++ iZoneBc ) + //{ + // ZoneBc * zoneBc = leafZoneBc[ iZoneBc ]; + // zoneBc->DumpBc(); + //} +} + +void Partition::DumpPartitionedGridFile() +{ + int fileId = -1; + std::string filename = "split1d.cgns"; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId); + std::cout << "fileId = " << fileId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = 1; + int iphysdim = 1; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "B" + std::to_string( iProc ) + "Zone" + std::to_string( iZone ); + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = "X"; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "cg_get_error() = " << cg_get_error() << "\n"; + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + //std::vector bccos; + + //this->DumpBc( splitZone ); + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->zoneIndex; + std::string donorname ="Zone" + std::to_string( id ); + std::string donorname1 ="ZZone" + std::to_string( id ); + + cg_1to1_write( fileId, baseId, zoneId, "Interface", donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + cg_1to1_write( fileId, baseId, zoneId, "Interface1", donorname1.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close(fileId); +} + +void Partition::ModifyZoneIndex() +{ + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + splitZone->SetZoneIndex( globalZoneId++ ); + } + } +} \ No newline at end of file diff --git a/example/partition/struct/1d/01c/Partition.h b/example/partition/struct/1d/01c/Partition.h new file mode 100644 index 00000000..55dc9cea --- /dev/null +++ b/example/partition/struct/1d/01c/Partition.h @@ -0,0 +1,171 @@ +#pragma once +#include +#include +#include + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + int regionAxis = -1; + std::vector start; + std::vector end; +public: + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + void SetRegion( std::vector &pnts ); + int ComputeRegionAxis(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void SetZoneBcFromParentBc( SplitBc * parentSplitBc ); + void InheritPatchBc( SplitBc * parentSplitBc ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +}; + + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + //int oriZoneId; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + void CreateBcFromParent(); + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNode; + int nTZone; + int nOriZone; + int nProc; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/01c/README.txt b/example/partition/struct/1d/01c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/01c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/01c/heat1dni81.cgns b/example/partition/struct/1d/01c/heat1dni81.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/partition/struct/1d/01c/heat1dni81.cgns differ diff --git a/example/partition/struct/1d/01c/main.cpp b/example/partition/struct/1d/01c/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/01c/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/01d/CMakeLists.txt b/example/partition/struct/1d/01d/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/1d/01d/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/01d/CgnsGrid.cpp b/example/partition/struct/1d/01d/CgnsGrid.cpp new file mode 100644 index 00000000..e58aa1ec --- /dev/null +++ b/example/partition/struct/1d/01d/CgnsGrid.cpp @@ -0,0 +1,231 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ +} + +std::vector Global::zones; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize(index_dim*3); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin(index_dim); + std::vector irmax(index_dim); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast(const_cast(normalList.data())); + + //std::cout << "normalList = "; + //for ( int i = 0; i < nNodes*iphysdim; ++ i ) + //{ + // std::cout << normal_d[ i ] << " "; + //} + //std::cout << "\n"; + } + } + } + cg_close(fileId); +} \ No newline at end of file diff --git a/example/partition/struct/1d/01d/CgnsGrid.h b/example/partition/struct/1d/01d/CgnsGrid.h new file mode 100644 index 00000000..b84abd1d --- /dev/null +++ b/example/partition/struct/1d/01d/CgnsGrid.h @@ -0,0 +1,69 @@ +#pragma once +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + std::vector pnts; +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static std::vector zones; + static void FreeData(); + static int cell_dim; + static int phys_dim; +}; + +void ReadCgnsGrid( const std::string & filename ); diff --git a/example/partition/struct/1d/01d/Partition.cpp b/example/partition/struct/1d/01d/Partition.cpp new file mode 100644 index 00000000..aa40583c --- /dev/null +++ b/example/partition/struct/1d/01d/Partition.cpp @@ -0,0 +1,1242 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->dim = 1; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo::~DimInfo() +{ +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + this->regionAxis = rhs.regionAxis; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } + this->ComputeRegionAxis(); +} + +int RangeRegion::ComputeRegionAxis() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] == this->end[ m ] ) + { + this->regionAxis = m; + return this->regionAxis; + } + } + return this->regionAxis; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + overlapRegion.start[ m ] = std::max( region1.start[ m ], region2.start[ m ] ); + overlapRegion.end [ m ] = std::min( region1.end [ m ], region2.end [ m ] ); + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +SplitBc * CreateSplitBc( RangeRegion & bcRegion, RangeRegion & zoneDomainRegion ) +{ + int sRegionAxis = bcRegion.ComputeRegionAxis(); + int tRegionAxis = zoneDomainRegion.ComputeRegionAxis(); + + //Two regions in different directions + if ( sRegionAxis != tRegionAxis ) + { + return 0; + } + + //Although the two regions are in the same direction, the coordinates are inconsistent. + if ( bcRegion.start[ sRegionAxis ] != zoneDomainRegion.start[ sRegionAxis ] ) + { + return 0; + } + + RangeRegion overlapRegion; + ComputeOverlapRegion( bcRegion, zoneDomainRegion, overlapRegion ); + + if ( CheckOverLapping( overlapRegion ) ) + { + SplitBc * splitBc = new SplitBc(); + splitBc->SetRegion( overlapRegion ); + return splitBc; + } + + int kkk = 1; + + return 0; +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + int kkk = 1; + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + SplitBc * splitBcL = new SplitBc(); + zoneL->AddSplitBc( splitBcL ); + + SplitBc * splitBcR = new SplitBc(); + zoneR->AddSplitBc( splitBcR ); + + splitBcL->splitZone = zoneL; + splitBcL->SetRegion( localInterfaceRegionL ); + splitBcL->bcType = BCTypeUserDefined; + + splitBcR->splitZone = zoneR; + splitBcR->SetRegion( localInterfaceRegionR ); + splitBcR->bcType = BCTypeUserDefined; + + //localInterfaceRegionL.MarkPatchBc(); + //localInterfaceRegionR.MarkPatchBc(); + + SplitBcPatch * splitBcPatchL = new SplitBcPatch(); + splitBcL->patch = splitBcPatchL; + splitBcPatchL->region = localInterfaceRegionR; + splitBcPatchL->splitZone = zoneR; + + SplitBcPatch * splitBcPatchR = new SplitBcPatch(); + splitBcR->patch = splitBcPatchR; + splitBcPatchR->region = localInterfaceRegionL; + splitBcPatchR->splitZone = zoneL; + + //splitBcL->Normalize(); + //splitBcR->Normalize(); +} + + +SplitBc::SplitBc() +{ +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::SetZoneBcFromParentBc( SplitBc * parentSplitBc ) +{ + this->bcType = parentSplitBc->bcType; + //this->LocalCoordinate(); + this->region.regionAxis = parentSplitBc->region.regionAxis; + this->InheritPatchBc( parentSplitBc ); +} + +void SplitBc::InheritPatchBc( SplitBc * parentSplitBc ) +{ + if ( ! ( this->bcType < 0 ) ) return; + + this->patch = new SplitBcPatch(); + + this->patch->splitZone = parentSplitBc->patch->splitZone; + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildPatchBc( tRangeBox, this->splitZone ); +} + +SplitBcPatch::SplitBcPatch() +{ +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL = new SplitZone(); + zoneL->SetParent( this ); + + zoneR = new SplitZone(); + zoneR->SetParent( this ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + std::vector< SplitBc * > & parentSplitBcList = this->parent->GetSplitBcList(); + + int nParentSplitBcs = parentSplitBcList.size(); + + for ( int iParentBc = 0; iParentBc < nParentSplitBcs; ++ iParentBc ) + { + SplitBc * parentSplitBc = parentSplitBcList[ iParentBc ]; + + this->CreateSplitBc( parentSplitBc ); + } +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + splitBc->ChangeRegionToLocalCoordinate(); + //splitBc->CreatePatchBc( parentSplitBc ); + + int kkk = 1; + } + } + else + { + int nChilds = parentSplitBc->child->size(); + for ( int iChild = 0; iChild < nChilds; ++ iChild ) + { + this->CreateSplitBc( ( * parentSplitBc->child )[ iChild ] ); + } + } +} + + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + ; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + this->ReadGrid(); + this->Split(); + this->ModifyZoneIndex(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGrid( "../heat1dni81.cgns" ); + + this->nOriZone = ::Global::zones.size(); + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + SplitBc * splitBc = new SplitBc(); + splitBcList.push_back( splitBc ); + + ZoneBc * zoneBc = zone->bccos[ iBcRegion ]; + + splitBc->splitZone = splitZone; + splitBc->bcType = zoneBc->bcType; + splitBc->SetRegion( zoneBc->pnts ); + } + + int kkk = 1; + + //splitZone->NormalizeBc(); + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + //this->SetZoneIndex(); +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + int index_dim = Global::cell_dim; + this->minNode = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + this->minNode *= 2; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = 0; + SplitZone * zoneR = 0; + + zone->Split( zoneL, zoneR, nCell ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + this->RemoveZoneFromUnsignedGroup( zone ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNode && nTarget > this->minNode ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ + //std::vector< ZoneBc * > leafZoneBc; + + //std::vector< ZoneBc * > & zoneBcList = splitZone->GetZoneBcList(); + + //for ( int i = 0; i < zoneBcList.size(); ++ i ) + //{ + // std::vector< ZoneBc * > cl = zoneBcList[ i ]->GetLeaves(); + // for ( int j = 0; j < cl.size(); ++ j ) + // { + // leafZoneBc.push_back( cl[ j ] ); + // } + //} + + //int nZoneBc = leafZoneBc.size(); + + //for ( int iZoneBc = 0; iZoneBc < nZoneBc; ++ iZoneBc ) + //{ + // ZoneBc * zoneBc = leafZoneBc[ iZoneBc ]; + // zoneBc->DumpBc(); + //} +} + +void Partition::DumpPartitionedGridFile() +{ + int fileId = -1; + std::string filename = "split1d.cgns"; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId); + std::cout << "fileId = " << fileId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = 1; + int iphysdim = 1; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "Zone" + std::to_string( splitZone->zoneIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = "X"; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "cg_get_error() = " << cg_get_error() << "\n"; + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->zoneIndex; + std::string donorname = "Zone" + std::to_string( id ); + + cg_1to1_write( fileId, baseId, zoneId, "Interface", donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close(fileId); +} + +void Partition::ModifyZoneIndex() +{ + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + splitZone->SetZoneIndex( globalZoneId++ ); + } + } +} \ No newline at end of file diff --git a/example/partition/struct/1d/01d/Partition.h b/example/partition/struct/1d/01d/Partition.h new file mode 100644 index 00000000..55dc9cea --- /dev/null +++ b/example/partition/struct/1d/01d/Partition.h @@ -0,0 +1,171 @@ +#pragma once +#include +#include +#include + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + int regionAxis = -1; + std::vector start; + std::vector end; +public: + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + void SetRegion( std::vector &pnts ); + int ComputeRegionAxis(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void SetZoneBcFromParentBc( SplitBc * parentSplitBc ); + void InheritPatchBc( SplitBc * parentSplitBc ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +}; + + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + //int oriZoneId; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + void CreateBcFromParent(); + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNode; + int nTZone; + int nOriZone; + int nProc; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/01d/README.txt b/example/partition/struct/1d/01d/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/01d/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/01d/heat1dni81.cgns b/example/partition/struct/1d/01d/heat1dni81.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/partition/struct/1d/01d/heat1dni81.cgns differ diff --git a/example/partition/struct/1d/01d/main.cpp b/example/partition/struct/1d/01d/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/01d/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/02/CMakeLists.txt b/example/partition/struct/1d/02/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/1d/02/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/02/CgnsGrid.cpp b/example/partition/struct/1d/02/CgnsGrid.cpp new file mode 100644 index 00000000..269276f9 --- /dev/null +++ b/example/partition/struct/1d/02/CgnsGrid.cpp @@ -0,0 +1,345 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones(fileId, baseId, &nzones); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[33]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex(index_dim,-1); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[i] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[normalDataType] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList(nNodes*iphysdim*sizeof(double)); + + std::vector pnts(npnts*index_dim); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc->pnts.push_back( range[ i ] ); + } + + zonebc->zoneid = gZoneId; + zonebc->bcType = BCTypeUserDefined; + + ZoneBcPatch * patch = new ZoneBcPatch(); + zonebc->patch = patch; + + patch->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + patch->donor_pnts.push_back( donor_range[ i ] ); + } + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close(fileId); +} \ No newline at end of file diff --git a/example/partition/struct/1d/02/CgnsGrid.h b/example/partition/struct/1d/02/CgnsGrid.h new file mode 100644 index 00000000..af67a321 --- /dev/null +++ b/example/partition/struct/1d/02/CgnsGrid.h @@ -0,0 +1,123 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/1d/02/Partition.cpp b/example/partition/struct/1d/02/Partition.cpp new file mode 100644 index 00000000..795cb892 --- /dev/null +++ b/example/partition/struct/1d/02/Partition.cpp @@ -0,0 +1,1267 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->dim = 1; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo::~DimInfo() +{ +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + this->regionAxis = rhs.regionAxis; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } + this->ComputeRegionAxis(); +} + +int RangeRegion::ComputeRegionAxis() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] == this->end[ m ] ) + { + this->regionAxis = m; + return this->regionAxis; + } + } + return this->regionAxis; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + overlapRegion.start[ m ] = std::max( region1.start[ m ], region2.start[ m ] ); + overlapRegion.end [ m ] = std::min( region1.end [ m ], region2.end [ m ] ); + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +SplitBc * CreateSplitBc( RangeRegion & bcRegion, RangeRegion & zoneDomainRegion ) +{ + int sRegionAxis = bcRegion.ComputeRegionAxis(); + int tRegionAxis = zoneDomainRegion.ComputeRegionAxis(); + + //Two regions in different directions + if ( sRegionAxis != tRegionAxis ) + { + return 0; + } + + //Although the two regions are in the same direction, the coordinates are inconsistent. + if ( bcRegion.start[ sRegionAxis ] != zoneDomainRegion.start[ sRegionAxis ] ) + { + return 0; + } + + RangeRegion overlapRegion; + ComputeOverlapRegion( bcRegion, zoneDomainRegion, overlapRegion ); + + if ( CheckOverLapping( overlapRegion ) ) + { + SplitBc * splitBc = new SplitBc(); + splitBc->SetRegion( overlapRegion ); + return splitBc; + } + + int kkk = 1; + + return 0; +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + int kkk = 1; + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + SplitBc * splitBcL = new SplitBc(); + zoneL->AddSplitBc( splitBcL ); + + SplitBc * splitBcR = new SplitBc(); + zoneR->AddSplitBc( splitBcR ); + + splitBcL->splitZone = zoneL; + splitBcL->SetRegion( localInterfaceRegionL ); + splitBcL->bcType = BCTypeUserDefined; + + splitBcR->splitZone = zoneR; + splitBcR->SetRegion( localInterfaceRegionR ); + splitBcR->bcType = BCTypeUserDefined; + + //localInterfaceRegionL.MarkPatchBc(); + //localInterfaceRegionR.MarkPatchBc(); + + SplitBcPatch * splitBcPatchL = new SplitBcPatch(); + splitBcL->patch = splitBcPatchL; + splitBcPatchL->region = localInterfaceRegionR; + splitBcPatchL->splitZone = zoneR; + + SplitBcPatch * splitBcPatchR = new SplitBcPatch(); + splitBcR->patch = splitBcPatchR; + splitBcPatchR->region = localInterfaceRegionL; + splitBcPatchR->splitZone = zoneL; + + //splitBcL->Normalize(); + //splitBcR->Normalize(); +} + + +SplitBc::SplitBc() +{ +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::SetZoneBcFromParentBc( SplitBc * parentSplitBc ) +{ + this->bcType = parentSplitBc->bcType; + //this->LocalCoordinate(); + this->region.regionAxis = parentSplitBc->region.regionAxis; + this->CreatePatchBc( parentSplitBc ); +} + +void SplitBc::CreatePatchBc( SplitBc * parentSplitBc ) +{ + if ( parentSplitBc->bcType != BCTypeUserDefined ) return; + + this->patch = new SplitBcPatch(); + this->patch->splitZone = parentSplitBc->patch->splitZone; + this->patch->SetRegion( parentSplitBc->patch->region ); + int kkk = 1; + + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildPatchBc( tRangeBox, this->splitZone ); +} + +SplitBcPatch::SplitBcPatch() +{ +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +void SplitBcPatch::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBcPatch::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL = new SplitZone(); + zoneL->SetParent( this ); + + zoneR = new SplitZone(); + zoneR->SetParent( this ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + std::vector< SplitBc * > & parentSplitBcList = this->parent->GetSplitBcList(); + + int nParentSplitBcs = parentSplitBcList.size(); + + for ( int iParentBc = 0; iParentBc < nParentSplitBcs; ++ iParentBc ) + { + SplitBc * parentSplitBc = parentSplitBcList[ iParentBc ]; + + this->CreateSplitBc( parentSplitBc ); + } +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + splitBc->ChangeRegionToLocalCoordinate(); + splitBc->CreatePatchBc( parentSplitBc ); + int kkk = 1; + } + } + else + { + int nChilds = parentSplitBc->child->size(); + for ( int iChild = 0; iChild < nChilds; ++ iChild ) + { + this->CreateSplitBc( ( * parentSplitBc->child )[ iChild ] ); + } + } +} + + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat1d2blocks.cgns"; + this->outName = "../heat1dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->ModifyZoneIndex(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + //ReadCgnsGrid( "../heat1dni81.cgns" ); + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + SplitBc * splitBc = new SplitBc(); + splitBcList.push_back( splitBc ); + + ZoneBc * zoneBc = zone->bccos[ iBcRegion ]; + + splitBc->splitZone = splitZone; + splitBc->bcType = zoneBc->bcType; + splitBc->SetRegion( zoneBc->pnts ); + if ( zoneBc->patch ) + { + SplitBcPatch * patch = new SplitBcPatch(); + splitBc->patch = patch; + + patch->splitZone = refZone[ zoneBc->patch->donor_zoneid ]; + patch->SetRegion( zoneBc->patch->donor_pnts ); + } + } + + int kkk = 1; + + //splitZone->NormalizeBc(); + } + int kkk = 1; +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + //this->SetZoneIndex(); +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + int index_dim = Global::cell_dim; + this->minNode = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + this->minNode *= 2; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = 0; + SplitZone * zoneR = 0; + + zone->Split( zoneL, zoneR, nCell ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + this->RemoveZoneFromUnsignedGroup( zone ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNode && nTarget > this->minNode ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ + //std::vector< ZoneBc * > leafZoneBc; + + //std::vector< ZoneBc * > & zoneBcList = splitZone->GetZoneBcList(); + + //for ( int i = 0; i < zoneBcList.size(); ++ i ) + //{ + // std::vector< ZoneBc * > cl = zoneBcList[ i ]->GetLeaves(); + // for ( int j = 0; j < cl.size(); ++ j ) + // { + // leafZoneBc.push_back( cl[ j ] ); + // } + //} + + //int nZoneBc = leafZoneBc.size(); + + //for ( int iZoneBc = 0; iZoneBc < nZoneBc; ++ iZoneBc ) + //{ + // ZoneBc * zoneBc = leafZoneBc[ iZoneBc ]; + // zoneBc->DumpBc(); + //} +} + +void Partition::DumpPartitionedGridFile() +{ + int fileId = -1; + std::string filename = this->outName; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = 1; + int iphysdim = 1; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "Zone" + std::to_string( splitZone->zoneIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = "X"; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "cg_get_error() = " << cg_get_error() << "\n"; + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->zoneIndex; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close(fileId); +} + +void Partition::ModifyZoneIndex() +{ + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + splitZone->SetZoneIndex( globalZoneId++ ); + } + } +} \ No newline at end of file diff --git a/example/partition/struct/1d/02/Partition.h b/example/partition/struct/1d/02/Partition.h new file mode 100644 index 00000000..b9c38c91 --- /dev/null +++ b/example/partition/struct/1d/02/Partition.h @@ -0,0 +1,177 @@ +#pragma once +#include +#include +#include + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + int regionAxis = -1; + std::vector start; + std::vector end; +public: + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + void SetRegion( std::vector &pnts ); + int ComputeRegionAxis(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void SetZoneBcFromParentBc( SplitBc * parentSplitBc ); + void CreatePatchBc( SplitBc * parentSplitBc ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); +}; + + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + //int oriZoneId; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + void CreateBcFromParent(); + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNode; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/02/README.txt b/example/partition/struct/1d/02/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/02/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/02/heat1d2blocks.cgns b/example/partition/struct/1d/02/heat1d2blocks.cgns new file mode 100644 index 00000000..4f4441f0 Binary files /dev/null and b/example/partition/struct/1d/02/heat1d2blocks.cgns differ diff --git a/example/partition/struct/1d/02/main.cpp b/example/partition/struct/1d/02/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/02/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/02a/CMakeLists.txt b/example/partition/struct/1d/02a/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/1d/02a/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/02a/CgnsGrid.cpp b/example/partition/struct/1d/02a/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/1d/02a/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/1d/02a/CgnsGrid.h b/example/partition/struct/1d/02a/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/1d/02a/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/1d/02a/Partition.cpp b/example/partition/struct/1d/02a/Partition.cpp new file mode 100644 index 00000000..e2e15648 --- /dev/null +++ b/example/partition/struct/1d/02a/Partition.cpp @@ -0,0 +1,619 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat1d2blocksv1.cgns"; + this->outName = "../heat1dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + //std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + std::vector< InterfaceSplitBc * > bc1to1List; + splitZone->GetLeafInterfaceBc( bc1to1List ); + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/1d/02a/Partition.h b/example/partition/struct/1d/02a/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/1d/02a/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/02a/README.txt b/example/partition/struct/1d/02a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/02a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/02a/SplitZone.cpp b/example/partition/struct/1d/02a/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/1d/02a/SplitZone.cpp @@ -0,0 +1,1091 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nChild = this->child.size(); + if ( nChild == 0 ) + { + leafInterfaceBcList.push_back( this ); + } + else + { + for ( int iChild = 0; iChild < nChild; ++ iChild ) + { + InterfaceSplitBc * interfaceSplitBc = this->child[ iChild ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } + } +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + +void SplitZone::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nInterfaceBcs = this->interfaceSplitBcList.size(); + for ( int i = 0; i < nInterfaceBcs; ++ i ) + { + InterfaceSplitBc * interfaceSplitBc = this->interfaceSplitBcList[ i ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/1d/02a/SplitZone.h b/example/partition/struct/1d/02a/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/1d/02a/SplitZone.h @@ -0,0 +1,196 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/1d/02a/heat1d2blocksv1.cgns b/example/partition/struct/1d/02a/heat1d2blocksv1.cgns new file mode 100644 index 00000000..4c9c4994 Binary files /dev/null and b/example/partition/struct/1d/02a/heat1d2blocksv1.cgns differ diff --git a/example/partition/struct/1d/02a/heat1dpart.cgns b/example/partition/struct/1d/02a/heat1dpart.cgns new file mode 100644 index 00000000..a51b966c Binary files /dev/null and b/example/partition/struct/1d/02a/heat1dpart.cgns differ diff --git a/example/partition/struct/1d/02a/main.cpp b/example/partition/struct/1d/02a/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/02a/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/02b/CMakeLists.txt b/example/partition/struct/1d/02b/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/1d/02b/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/02b/CgnsGrid.cpp b/example/partition/struct/1d/02b/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/1d/02b/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/1d/02b/CgnsGrid.h b/example/partition/struct/1d/02b/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/1d/02b/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/1d/02b/Partition.cpp b/example/partition/struct/1d/02b/Partition.cpp new file mode 100644 index 00000000..291c15e4 --- /dev/null +++ b/example/partition/struct/1d/02b/Partition.cpp @@ -0,0 +1,619 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat1d2blocksv1.cgns"; + this->outName = "../heat1dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + //std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + std::vector< InterfaceSplitBc * > bc1to1List; + splitZone->GetLeafInterfaceBc( bc1to1List ); + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/1d/02b/Partition.h b/example/partition/struct/1d/02b/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/1d/02b/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/02b/README.txt b/example/partition/struct/1d/02b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/02b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/02b/SplitZone.cpp b/example/partition/struct/1d/02b/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/1d/02b/SplitZone.cpp @@ -0,0 +1,1091 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nChild = this->child.size(); + if ( nChild == 0 ) + { + leafInterfaceBcList.push_back( this ); + } + else + { + for ( int iChild = 0; iChild < nChild; ++ iChild ) + { + InterfaceSplitBc * interfaceSplitBc = this->child[ iChild ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } + } +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + +void SplitZone::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nInterfaceBcs = this->interfaceSplitBcList.size(); + for ( int i = 0; i < nInterfaceBcs; ++ i ) + { + InterfaceSplitBc * interfaceSplitBc = this->interfaceSplitBcList[ i ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/1d/02b/SplitZone.h b/example/partition/struct/1d/02b/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/1d/02b/SplitZone.h @@ -0,0 +1,196 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/1d/02b/heat1d2blocksv1.cgns b/example/partition/struct/1d/02b/heat1d2blocksv1.cgns new file mode 100644 index 00000000..4c9c4994 Binary files /dev/null and b/example/partition/struct/1d/02b/heat1d2blocksv1.cgns differ diff --git a/example/partition/struct/1d/02b/heat1dpart.cgns b/example/partition/struct/1d/02b/heat1dpart.cgns new file mode 100644 index 00000000..ad02ab7e Binary files /dev/null and b/example/partition/struct/1d/02b/heat1dpart.cgns differ diff --git a/example/partition/struct/1d/02b/main.cpp b/example/partition/struct/1d/02b/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/02b/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/03/CMakeLists.txt b/example/partition/struct/1d/03/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/1d/03/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/03/CgnsGrid.cpp b/example/partition/struct/1d/03/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/1d/03/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/1d/03/CgnsGrid.h b/example/partition/struct/1d/03/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/1d/03/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/1d/03/Partition.cpp b/example/partition/struct/1d/03/Partition.cpp new file mode 100644 index 00000000..ae983863 --- /dev/null +++ b/example/partition/struct/1d/03/Partition.cpp @@ -0,0 +1,619 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat1d2blocksv2.cgns"; + this->outName = "../heat1dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + //std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + std::vector< InterfaceSplitBc * > bc1to1List; + splitZone->GetLeafInterfaceBc( bc1to1List ); + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/1d/03/Partition.h b/example/partition/struct/1d/03/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/1d/03/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/03/README.txt b/example/partition/struct/1d/03/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/03/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/03/SplitZone.cpp b/example/partition/struct/1d/03/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/1d/03/SplitZone.cpp @@ -0,0 +1,1091 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nChild = this->child.size(); + if ( nChild == 0 ) + { + leafInterfaceBcList.push_back( this ); + } + else + { + for ( int iChild = 0; iChild < nChild; ++ iChild ) + { + InterfaceSplitBc * interfaceSplitBc = this->child[ iChild ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } + } +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + +void SplitZone::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nInterfaceBcs = this->interfaceSplitBcList.size(); + for ( int i = 0; i < nInterfaceBcs; ++ i ) + { + InterfaceSplitBc * interfaceSplitBc = this->interfaceSplitBcList[ i ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/1d/03/SplitZone.h b/example/partition/struct/1d/03/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/1d/03/SplitZone.h @@ -0,0 +1,196 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/1d/03/heat1d2blocksv2.cgns b/example/partition/struct/1d/03/heat1d2blocksv2.cgns new file mode 100644 index 00000000..de6cfb78 Binary files /dev/null and b/example/partition/struct/1d/03/heat1d2blocksv2.cgns differ diff --git a/example/partition/struct/1d/03/heat1dpart.cgns b/example/partition/struct/1d/03/heat1dpart.cgns new file mode 100644 index 00000000..cd6c8473 Binary files /dev/null and b/example/partition/struct/1d/03/heat1dpart.cgns differ diff --git a/example/partition/struct/1d/03/main.cpp b/example/partition/struct/1d/03/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/03/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/1to4blocks/01/CMakeLists.txt b/example/partition/struct/1d/1to4blocks/01/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/1d/1to4blocks/01/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/1to4blocks/01/CgnsGrid.cpp b/example/partition/struct/1d/1to4blocks/01/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/1d/1to4blocks/01/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/1d/1to4blocks/01/CgnsGrid.h b/example/partition/struct/1d/1to4blocks/01/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/1d/1to4blocks/01/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/1d/1to4blocks/01/Partition.cpp b/example/partition/struct/1d/1to4blocks/01/Partition.cpp new file mode 100644 index 00000000..c262d5dc --- /dev/null +++ b/example/partition/struct/1d/1to4blocks/01/Partition.cpp @@ -0,0 +1,619 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat1d1blocksv1.cgns"; + this->outName = "../heat1dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + //std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + std::vector< InterfaceSplitBc * > bc1to1List; + splitZone->GetLeafInterfaceBc( bc1to1List ); + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/1d/1to4blocks/01/Partition.h b/example/partition/struct/1d/1to4blocks/01/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/1d/1to4blocks/01/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/1to4blocks/01/README.txt b/example/partition/struct/1d/1to4blocks/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/1to4blocks/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/1to4blocks/01/SplitZone.cpp b/example/partition/struct/1d/1to4blocks/01/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/1d/1to4blocks/01/SplitZone.cpp @@ -0,0 +1,1091 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nChild = this->child.size(); + if ( nChild == 0 ) + { + leafInterfaceBcList.push_back( this ); + } + else + { + for ( int iChild = 0; iChild < nChild; ++ iChild ) + { + InterfaceSplitBc * interfaceSplitBc = this->child[ iChild ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } + } +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + +void SplitZone::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nInterfaceBcs = this->interfaceSplitBcList.size(); + for ( int i = 0; i < nInterfaceBcs; ++ i ) + { + InterfaceSplitBc * interfaceSplitBc = this->interfaceSplitBcList[ i ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/1d/1to4blocks/01/SplitZone.h b/example/partition/struct/1d/1to4blocks/01/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/1d/1to4blocks/01/SplitZone.h @@ -0,0 +1,196 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/1d/1to4blocks/01/heat1d1blocksv1.cgns b/example/partition/struct/1d/1to4blocks/01/heat1d1blocksv1.cgns new file mode 100644 index 00000000..1d0a3fb2 Binary files /dev/null and b/example/partition/struct/1d/1to4blocks/01/heat1d1blocksv1.cgns differ diff --git a/example/partition/struct/1d/1to4blocks/01/heat1dpart.cgns b/example/partition/struct/1d/1to4blocks/01/heat1dpart.cgns new file mode 100644 index 00000000..df5ffc5f Binary files /dev/null and b/example/partition/struct/1d/1to4blocks/01/heat1dpart.cgns differ diff --git a/example/partition/struct/1d/1to4blocks/01/main.cpp b/example/partition/struct/1d/1to4blocks/01/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/1to4blocks/01/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/1d/1to8blocks/01/CMakeLists.txt b/example/partition/struct/1d/1to8blocks/01/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/1d/1to8blocks/01/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/1d/1to8blocks/01/CgnsGrid.cpp b/example/partition/struct/1d/1to8blocks/01/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/1d/1to8blocks/01/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/1d/1to8blocks/01/CgnsGrid.h b/example/partition/struct/1d/1to8blocks/01/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/1d/1to8blocks/01/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/1d/1to8blocks/01/Partition.cpp b/example/partition/struct/1d/1to8blocks/01/Partition.cpp new file mode 100644 index 00000000..93c40c99 --- /dev/null +++ b/example/partition/struct/1d/1to8blocks/01/Partition.cpp @@ -0,0 +1,619 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat1d1blocksv1.cgns"; + this->outName = "../heat1dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 8; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + //std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + std::vector< InterfaceSplitBc * > bc1to1List; + splitZone->GetLeafInterfaceBc( bc1to1List ); + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/1d/1to8blocks/01/Partition.h b/example/partition/struct/1d/1to8blocks/01/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/1d/1to8blocks/01/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/1d/1to8blocks/01/README.txt b/example/partition/struct/1d/1to8blocks/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d/1to8blocks/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d/1to8blocks/01/SplitZone.cpp b/example/partition/struct/1d/1to8blocks/01/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/1d/1to8blocks/01/SplitZone.cpp @@ -0,0 +1,1091 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nChild = this->child.size(); + if ( nChild == 0 ) + { + leafInterfaceBcList.push_back( this ); + } + else + { + for ( int iChild = 0; iChild < nChild; ++ iChild ) + { + InterfaceSplitBc * interfaceSplitBc = this->child[ iChild ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } + } +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + +void SplitZone::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nInterfaceBcs = this->interfaceSplitBcList.size(); + for ( int i = 0; i < nInterfaceBcs; ++ i ) + { + InterfaceSplitBc * interfaceSplitBc = this->interfaceSplitBcList[ i ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/1d/1to8blocks/01/SplitZone.h b/example/partition/struct/1d/1to8blocks/01/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/1d/1to8blocks/01/SplitZone.h @@ -0,0 +1,196 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/1d/1to8blocks/01/heat1d1blocksv1.cgns b/example/partition/struct/1d/1to8blocks/01/heat1d1blocksv1.cgns new file mode 100644 index 00000000..1d0a3fb2 Binary files /dev/null and b/example/partition/struct/1d/1to8blocks/01/heat1d1blocksv1.cgns differ diff --git a/example/partition/struct/1d/1to8blocks/01/main.cpp b/example/partition/struct/1d/1to8blocks/01/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d/1to8blocks/01/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01/CMakeLists.txt b/example/partition/struct/2d/stage1/01/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/2d/stage1/01/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01/CgnsGrid.cpp new file mode 100644 index 00000000..d287afcb --- /dev/null +++ b/example/partition/struct/2d/stage1/01/CgnsGrid.cpp @@ -0,0 +1,345 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc->pnts.push_back( range[ i ] ); + } + + zonebc->zoneid = gZoneId; + zonebc->bcType = BCTypeUserDefined; + + ZoneBcPatch * patch = new ZoneBcPatch(); + zonebc->patch = patch; + + patch->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + patch->donor_pnts.push_back( donor_range[ i ] ); + } + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01/CgnsGrid.h b/example/partition/struct/2d/stage1/01/CgnsGrid.h new file mode 100644 index 00000000..af67a321 --- /dev/null +++ b/example/partition/struct/2d/stage1/01/CgnsGrid.h @@ -0,0 +1,123 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01/Partition.cpp b/example/partition/struct/2d/stage1/01/Partition.cpp new file mode 100644 index 00000000..022906d4 --- /dev/null +++ b/example/partition/struct/2d/stage1/01/Partition.cpp @@ -0,0 +1,1461 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); + //this->dim = 1; + //dimList.resize( this->dim, 1 ); + //oriPoint.resize( this->dim, 0 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); + //this->start.resize( nSize ); + //this->end.resize( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + this->regionAxis = rhs.regionAxis; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } + this->ComputeRegionAxis(); +} + +int RangeRegion::ComputeRegionAxis() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] == this->end[ m ] ) + { + this->regionAxis = m; + return this->regionAxis; + } + } + return this->regionAxis; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + for ( int m = 0; m < index_dim; ++ m ) + { + overlapRegion.start[ m ] = std::max( region1.start[ m ], region2.start[ m ] ); + overlapRegion.end [ m ] = std::min( region1.end [ m ], region2.end [ m ] ); + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +SplitBc * CreateSplitBc( RangeRegion & bcRegion, RangeRegion & zoneDomainRegion ) +{ + int sRegionAxis = bcRegion.ComputeRegionAxis(); + int tRegionAxis = zoneDomainRegion.ComputeRegionAxis(); + + //Two regions in different directions + if ( sRegionAxis != tRegionAxis ) + { + return 0; + } + + //Although the two regions are in the same direction, the coordinates are inconsistent. + if ( bcRegion.start[ sRegionAxis ] != zoneDomainRegion.start[ sRegionAxis ] ) + { + return 0; + } + + RangeRegion overlapRegion; + ComputeOverlapRegion( bcRegion, zoneDomainRegion, overlapRegion ); + + if ( CheckOverLapping( overlapRegion ) ) + { + SplitBc * splitBc = new SplitBc(); + splitBc->SetRegion( overlapRegion ); + return splitBc; + } + + int kkk = 1; + + return 0; +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + int kkk = 1; + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + SplitBc * splitBcL = new SplitBc(); + zoneL->AddSplitBc( splitBcL ); + + SplitBc * splitBcR = new SplitBc(); + zoneR->AddSplitBc( splitBcR ); + + splitBcL->splitZone = zoneL; + splitBcL->SetRegion( localInterfaceRegionL ); + splitBcL->bcType = BCTypeUserDefined; + + splitBcR->splitZone = zoneR; + splitBcR->SetRegion( localInterfaceRegionR ); + splitBcR->bcType = BCTypeUserDefined; + + //localInterfaceRegionL.MarkPatchBc(); + //localInterfaceRegionR.MarkPatchBc(); + + SplitBcPatch * splitBcPatchL = new SplitBcPatch(); + splitBcL->patch = splitBcPatchL; + splitBcPatchL->region = localInterfaceRegionR; + splitBcPatchL->splitZone = zoneR; + + SplitBcPatch * splitBcPatchR = new SplitBcPatch(); + splitBcR->patch = splitBcPatchR; + splitBcPatchR->region = localInterfaceRegionL; + splitBcPatchR->splitZone = zoneL; + + //splitBcL->Normalize(); + //splitBcR->Normalize(); +} + + +SplitBc::SplitBc() +{ + this->region.Init( Dim::dim ); +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::SetZoneBcFromParentBc( SplitBc * parentSplitBc ) +{ + this->bcType = parentSplitBc->bcType; + //this->LocalCoordinate(); + this->region.regionAxis = parentSplitBc->region.regionAxis; + this->CreatePatchBc( parentSplitBc ); +} + +void SplitBc::CreatePatchBc( SplitBc * parentSplitBc ) +{ + if ( parentSplitBc->bcType != BCTypeUserDefined ) return; + + this->patch = new SplitBcPatch(); + this->patch->splitZone = parentSplitBc->patch->splitZone; + this->patch->SetRegion( parentSplitBc->patch->region ); + int kkk = 1; + + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildPatchBc( tRangeBox, this->splitZone ); +} + +SplitBcPatch::SplitBcPatch() +{ + this->region.Init( Dim::dim ); +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +void SplitBcPatch::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBcPatch::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL = new SplitZone(); + zoneL->SetParent( this ); + + zoneR = new SplitZone(); + zoneR->SetParent( this ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + std::vector< SplitBc * > & parentSplitBcList = this->parent->GetSplitBcList(); + + int nParentSplitBcs = parentSplitBcList.size(); + + for ( int iParentBc = 0; iParentBc < nParentSplitBcs; ++ iParentBc ) + { + SplitBc * parentSplitBc = parentSplitBcList[ iParentBc ]; + + this->CreateSplitBc( parentSplitBc ); + } +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + splitBc->ChangeRegionToLocalCoordinate(); + splitBc->CreatePatchBc( parentSplitBc ); + int kkk = 1; + } + } + else + { + int nChilds = parentSplitBc->child->size(); + for ( int iChild = 0; iChild < nChilds; ++ iChild ) + { + this->CreateSplitBc( ( * parentSplitBc->child )[ iChild ] ); + } + } +} + + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + //this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->ModifyZoneIndex(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + SplitBc * splitBc = new SplitBc(); + splitBcList.push_back( splitBc ); + + ZoneBc * zoneBc = zone->bccos[ iBcRegion ]; + + splitBc->splitZone = splitZone; + splitBc->bcType = zoneBc->bcType; + splitBc->SetRegion( zoneBc->pnts ); + if ( zoneBc->patch ) + { + SplitBcPatch * patch = new SplitBcPatch(); + splitBc->patch = patch; + + patch->splitZone = refZone[ zoneBc->patch->donor_zoneid ]; + patch->SetRegion( zoneBc->patch->donor_pnts ); + } + } + + int kkk = 1; + } + int kkk = 1; +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + //this->SetZoneIndex(); +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNode = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNode *= 2; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = 0; + SplitZone * zoneR = 0; + + zone->Split( zoneL, zoneR, nCell ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + this->RemoveZoneFromUnsignedGroup( zone ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNode && nTarget > this->minNode ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ + //std::vector< ZoneBc * > leafZoneBc; + + //std::vector< ZoneBc * > & zoneBcList = splitZone->GetZoneBcList(); + + //for ( int i = 0; i < zoneBcList.size(); ++ i ) + //{ + // std::vector< ZoneBc * > cl = zoneBcList[ i ]->GetLeaves(); + // for ( int j = 0; j < cl.size(); ++ j ) + // { + // leafZoneBc.push_back( cl[ j ] ); + // } + //} + + //int nZoneBc = leafZoneBc.size(); + + //for ( int iZoneBc = 0; iZoneBc < nZoneBc; ++ iZoneBc ) + //{ + // ZoneBc * zoneBc = leafZoneBc[ iZoneBc ]; + // zoneBc->DumpBc(); + //} +} + +void Partition::DumpMultiBasePartitionedGridFile() +{ + int fileId = -1; + std::string filename = this->outName; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "Zone" + std::to_string( splitZone->zoneIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "cg_get_error() = " << cg_get_error() << "\n"; + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->zoneIndex; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::DumpPartitionedGridFile() +{ + int fileId = -1; + std::string filename = this->outName; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "Zone" + std::to_string( splitZone->zoneIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "cg_get_error() = " << cg_get_error() << "\n"; + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->zoneIndex; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + splitZone->SetZoneIndex( globalZoneId++ ); + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01/Partition.h b/example/partition/struct/2d/stage1/01/Partition.h new file mode 100644 index 00000000..cc384b21 --- /dev/null +++ b/example/partition/struct/2d/stage1/01/Partition.h @@ -0,0 +1,185 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + int regionAxis = -1; + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + void SetRegion( std::vector &pnts ); + int ComputeRegionAxis(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void SetZoneBcFromParentBc( SplitBc * parentSplitBc ); + void CreatePatchBc( SplitBc * parentSplitBc ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); +}; + + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + void CreateBcFromParent(); + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNode; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpMultiBasePartitionedGridFile(); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01/README.txt b/example/partition/struct/2d/stage1/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01/heat2d2blocks.cgns new file mode 100644 index 00000000..a9fd7ac5 Binary files /dev/null and b/example/partition/struct/2d/stage1/01/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01/main.cpp b/example/partition/struct/2d/stage1/01/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01a/CMakeLists.txt b/example/partition/struct/2d/stage1/01a/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/2d/stage1/01a/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01a/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01a/CgnsGrid.cpp new file mode 100644 index 00000000..d287afcb --- /dev/null +++ b/example/partition/struct/2d/stage1/01a/CgnsGrid.cpp @@ -0,0 +1,345 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc->pnts.push_back( range[ i ] ); + } + + zonebc->zoneid = gZoneId; + zonebc->bcType = BCTypeUserDefined; + + ZoneBcPatch * patch = new ZoneBcPatch(); + zonebc->patch = patch; + + patch->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + patch->donor_pnts.push_back( donor_range[ i ] ); + } + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01a/CgnsGrid.h b/example/partition/struct/2d/stage1/01a/CgnsGrid.h new file mode 100644 index 00000000..af67a321 --- /dev/null +++ b/example/partition/struct/2d/stage1/01a/CgnsGrid.h @@ -0,0 +1,123 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01a/Partition.cpp b/example/partition/struct/2d/stage1/01a/Partition.cpp new file mode 100644 index 00000000..6b35b19b --- /dev/null +++ b/example/partition/struct/2d/stage1/01a/Partition.cpp @@ -0,0 +1,1452 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + this->regionAxis = rhs.regionAxis; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } + this->ComputeRegionAxis(); +} + +int RangeRegion::ComputeRegionAxis() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] == this->end[ m ] ) + { + this->regionAxis = m; + return this->regionAxis; + } + } + return this->regionAxis; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +//bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +//{ +// int index_dim = region1.start.size(); +// overlapRegion.Init( index_dim ); +// for ( int m = 0; m < index_dim; ++ m ) +// { +// overlapRegion.start[ m ] = std::max( region1.start[ m ], region2.start[ m ] ); +// overlapRegion.end [ m ] = std::min( region1.end [ m ], region2.end [ m ] ); +// } +// +// return CheckOverLapping( overlapRegion ); +//} + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + int kkk = 1; + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + SplitBc * splitBcL = new SplitBc(); + zoneL->AddSplitBc( splitBcL ); + + SplitBc * splitBcR = new SplitBc(); + zoneR->AddSplitBc( splitBcR ); + + splitBcL->splitZone = zoneL; + splitBcL->SetRegion( localInterfaceRegionL ); + splitBcL->bcType = BCTypeUserDefined; + + splitBcR->splitZone = zoneR; + splitBcR->SetRegion( localInterfaceRegionR ); + splitBcR->bcType = BCTypeUserDefined; + + //localInterfaceRegionL.MarkPatchBc(); + //localInterfaceRegionR.MarkPatchBc(); + + SplitBcPatch * splitBcPatchL = new SplitBcPatch(); + splitBcL->patch = splitBcPatchL; + splitBcPatchL->region = localInterfaceRegionR; + splitBcPatchL->splitZone = zoneR; + + SplitBcPatch * splitBcPatchR = new SplitBcPatch(); + splitBcR->patch = splitBcPatchR; + splitBcPatchR->region = localInterfaceRegionL; + splitBcPatchR->splitZone = zoneL; + + //splitBcL->Normalize(); + //splitBcR->Normalize(); +} + + +SplitBc::SplitBc() +{ + this->region.Init( Dim::dim ); +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::SetZoneBcFromParentBc( SplitBc * parentSplitBc ) +{ + this->bcType = parentSplitBc->bcType; + //this->LocalCoordinate(); + this->region.regionAxis = parentSplitBc->region.regionAxis; + this->CreatePatchBc( parentSplitBc ); +} + +void SplitBc::CreatePatchBc( SplitBc * parentSplitBc ) +{ + if ( parentSplitBc->bcType != BCTypeUserDefined ) return; + + this->patch = new SplitBcPatch(); + this->patch->splitZone = parentSplitBc->patch->splitZone; + this->patch->SetRegion( parentSplitBc->patch->region ); + int kkk = 1; + + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildPatchBc( tRangeBox, this->splitZone ); +} + +SplitBcPatch::SplitBcPatch() +{ + this->region.Init( Dim::dim ); +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +void SplitBcPatch::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBcPatch::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL = new SplitZone(); + zoneL->SetParent( this ); + + zoneR = new SplitZone(); + zoneR->SetParent( this ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + std::vector< SplitBc * > & parentSplitBcList = this->parent->GetSplitBcList(); + + int nParentSplitBcs = parentSplitBcList.size(); + + for ( int iParentBc = 0; iParentBc < nParentSplitBcs; ++ iParentBc ) + { + SplitBc * parentSplitBc = parentSplitBcList[ iParentBc ]; + + this->CreateSplitBc( parentSplitBc ); + } +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + splitBc->ChangeRegionToLocalCoordinate(); + splitBc->CreatePatchBc( parentSplitBc ); + int kkk = 1; + } + } + else + { + int nChilds = parentSplitBc->child->size(); + for ( int iChild = 0; iChild < nChilds; ++ iChild ) + { + this->CreateSplitBc( ( * parentSplitBc->child )[ iChild ] ); + } + } +} + + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d1blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + //this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->ModifyZoneIndex(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + SplitBc * splitBc = new SplitBc(); + splitBcList.push_back( splitBc ); + + ZoneBc * zoneBc = zone->bccos[ iBcRegion ]; + + splitBc->splitZone = splitZone; + splitBc->bcType = zoneBc->bcType; + splitBc->SetRegion( zoneBc->pnts ); + if ( zoneBc->patch ) + { + SplitBcPatch * patch = new SplitBcPatch(); + splitBc->patch = patch; + + patch->splitZone = refZone[ zoneBc->patch->donor_zoneid ]; + patch->SetRegion( zoneBc->patch->donor_pnts ); + } + } + + int kkk = 1; + } + int kkk = 1; +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + //this->SetZoneIndex(); +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNode = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNode *= 2; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = 0; + SplitZone * zoneR = 0; + + zone->Split( zoneL, zoneR, nCell ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + this->RemoveZoneFromUnsignedGroup( zone ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNode && nTarget > this->minNode ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ + //std::vector< ZoneBc * > leafZoneBc; + + //std::vector< ZoneBc * > & zoneBcList = splitZone->GetZoneBcList(); + + //for ( int i = 0; i < zoneBcList.size(); ++ i ) + //{ + // std::vector< ZoneBc * > cl = zoneBcList[ i ]->GetLeaves(); + // for ( int j = 0; j < cl.size(); ++ j ) + // { + // leafZoneBc.push_back( cl[ j ] ); + // } + //} + + //int nZoneBc = leafZoneBc.size(); + + //for ( int iZoneBc = 0; iZoneBc < nZoneBc; ++ iZoneBc ) + //{ + // ZoneBc * zoneBc = leafZoneBc[ iZoneBc ]; + // zoneBc->DumpBc(); + //} +} + +void Partition::DumpMultiBasePartitionedGridFile() +{ + int fileId = -1; + std::string filename = this->outName; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "Zone" + std::to_string( splitZone->zoneIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "cg_get_error() = " << cg_get_error() << "\n"; + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->zoneIndex; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::DumpPartitionedGridFile() +{ + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + std::cout << "cg_get_error() 111 = " << cg_get_error() << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "Zone" + std::to_string( splitZone->zoneIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "cg_get_error() = " << cg_get_error() << "\n"; + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->zoneIndex; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + splitZone->SetZoneIndex( globalZoneId++ ); + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01a/Partition.h b/example/partition/struct/2d/stage1/01a/Partition.h new file mode 100644 index 00000000..cc384b21 --- /dev/null +++ b/example/partition/struct/2d/stage1/01a/Partition.h @@ -0,0 +1,185 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + int regionAxis = -1; + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + void SetRegion( std::vector &pnts ); + int ComputeRegionAxis(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void SetZoneBcFromParentBc( SplitBc * parentSplitBc ); + void CreatePatchBc( SplitBc * parentSplitBc ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); +}; + + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + void CreateBcFromParent(); + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNode; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpMultiBasePartitionedGridFile(); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01a/README.txt b/example/partition/struct/2d/stage1/01a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01a/heat2d1blocks.cgns b/example/partition/struct/2d/stage1/01a/heat2d1blocks.cgns new file mode 100644 index 00000000..ba7fd0a4 Binary files /dev/null and b/example/partition/struct/2d/stage1/01a/heat2d1blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01a/main.cpp b/example/partition/struct/2d/stage1/01a/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01a/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01b/CMakeLists.txt b/example/partition/struct/2d/stage1/01b/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/2d/stage1/01b/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01b/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01b/CgnsGrid.cpp new file mode 100644 index 00000000..d287afcb --- /dev/null +++ b/example/partition/struct/2d/stage1/01b/CgnsGrid.cpp @@ -0,0 +1,345 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc->pnts.push_back( range[ i ] ); + } + + zonebc->zoneid = gZoneId; + zonebc->bcType = BCTypeUserDefined; + + ZoneBcPatch * patch = new ZoneBcPatch(); + zonebc->patch = patch; + + patch->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + patch->donor_pnts.push_back( donor_range[ i ] ); + } + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01b/CgnsGrid.h b/example/partition/struct/2d/stage1/01b/CgnsGrid.h new file mode 100644 index 00000000..af67a321 --- /dev/null +++ b/example/partition/struct/2d/stage1/01b/CgnsGrid.h @@ -0,0 +1,123 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01b/Partition.cpp b/example/partition/struct/2d/stage1/01b/Partition.cpp new file mode 100644 index 00000000..0ef2b155 --- /dev/null +++ b/example/partition/struct/2d/stage1/01b/Partition.cpp @@ -0,0 +1,1547 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + this->regionAxis = rhs.regionAxis; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } + this->ComputeRegionAxis(); +} + +int RangeRegion::ComputeRegionAxis() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] == this->end[ m ] ) + { + this->regionAxis = m; + return this->regionAxis; + } + } + return this->regionAxis; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + int kkk = 1; + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + SplitBc * splitBcL = new SplitBc(); + zoneL->AddSplitBc( splitBcL ); + + SplitBc * splitBcR = new SplitBc(); + zoneR->AddSplitBc( splitBcR ); + + splitBcL->splitZone = zoneL; + splitBcL->SetRegion( localInterfaceRegionL ); + splitBcL->bcType = BCTypeUserDefined; + + splitBcR->splitZone = zoneR; + splitBcR->SetRegion( localInterfaceRegionR ); + splitBcR->bcType = BCTypeUserDefined; + + //localInterfaceRegionL.MarkPatchBc(); + //localInterfaceRegionR.MarkPatchBc(); + + SplitBcPatch * splitBcPatchL = new SplitBcPatch(); + splitBcL->patch = splitBcPatchL; + splitBcPatchL->region = localInterfaceRegionR; + splitBcPatchL->splitZone = zoneR; + + SplitBcPatch * splitBcPatchR = new SplitBcPatch(); + splitBcR->patch = splitBcPatchR; + splitBcPatchR->region = localInterfaceRegionL; + splitBcPatchR->splitZone = zoneL; + + //splitBcL->Normalize(); + //splitBcR->Normalize(); +} + + +SplitBc::SplitBc() +{ + this->region.Init( Dim::dim ); +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::CreateInterfaceBcFromParentBc( SplitBc * parentSplitBc ) +{ + if ( parentSplitBc->bcType != BCTypeUserDefined ) return; + + this->patch = new SplitBcPatch(); + this->patch->splitZone = parentSplitBc->patch->splitZone; + this->patch->SetRegion( parentSplitBc->patch->region ); + int kkk = 1; + + //Find the block corresponding to this docking boundary + //From patch->splitZone, find the corresponding docking boundary according to the size of overlapt + //The boundary conditions on the opposite side must change due to the split of this block. + //Here, the relevant boundaries are added to the sub-boundaries. + + RangeRegion targetRegionBox; + targetRegionBox = parentSplitBc->patch->region; + + SplitZone * targetZone = this->patch->splitZone; + + targetZone->CreateChildInterfaceBc( targetRegionBox, this->splitZone ); + + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildInterfaceBc( tRangeBox, this->splitZone ); +} + + +SplitBcPatch::SplitBcPatch() +{ + this->region.Init( Dim::dim ); +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +void SplitBcPatch::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBcPatch::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + std::vector< SplitBc * > & parentSplitBcList = this->parent->GetSplitBcList(); + + int nParentSplitBcs = parentSplitBcList.size(); + + for ( int iParentBc = 0; iParentBc < nParentSplitBcs; ++ iParentBc ) + { + SplitBc * parentSplitBc = parentSplitBcList[ iParentBc ]; + + this->CreateSplitBc( parentSplitBc ); + } +} + +void SplitZone::CreateChildInterfaceBc( RangeRegion &targeRegionBox, SplitZone * sourceZone ) +{ + std::vector< SplitBc * > & splitBcList = this->GetSplitBcList(); + + int nSplitBcs = splitBcList.size(); + + for ( int iSplitBc = 0; iSplitBc < nSplitBcs; ++ iSplitBc ) + { + SplitBc * splitBc = splitBcList[ iSplitBc ]; + + //Only consider the interface boundaries + if ( splitBc->bcType != BCTypeUserDefined ) continue; + + if ( this->CreateChildInterfaceBc( splitBc, targeRegionBox, sourceZone ) ) return; + } +} + +bool SplitZone::CreateChildInterfaceBc( SplitBc * interfaceBc, RangeRegion & targeRegionBox, SplitZone * sourceZone ) +{ + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( interfaceBc->region, targeRegionBox, overlapRegion ); + if ( ! overlap_flag ) return false; + + //1. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬µ«ÊÇinterfaceBcûÓÐchild£¬Ôò´ËsplitBc×÷ΪinterfaceBcµÄÒ»¸öchild + //2. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍËùÓÐchildûÓн»¼¯£¬ + // ÔòsplitBc¼ÓÈëinterfaceBcµÄÒ»¸öchild + //3. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍchildÓн»¼¯£¬Ôò´Ëchild×÷ΪеÄinterfaceBc + + std::vector< SplitBc * > * child = interfaceBc->child; + + if ( interfaceBc->child ) + { + for ( int iChild = 0; iChild < interfaceBc->child->size(); ++ iChild ) + { + SplitBc * childSplitBc = ( * interfaceBc->child )[ iChild ]; + if ( this->CreateChildInterfaceBc( childSplitBc, targeRegionBox, sourceZone ) ) return true; + } + } + else + { + interfaceBc->child = new std::vector< SplitBc * >(); + } + + SplitBc * childInterfaceBc = new SplitBc(); + //this->AddSplitBc( splitBc ); + + childInterfaceBc->SetRegion( overlapRegion ); + childInterfaceBc->bcType = interfaceBc->bcType; + childInterfaceBc->splitZone = interfaceBc->splitZone; + + + interfaceBc->child->push_back( childInterfaceBc ); + + //vector< int > & parentFaceDirectionContainer = interfaceBc->GetFaceDirectionContainer(); + //vector< int > & faceDirectionContainer = childInterfaceBc->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // faceDirectionContainer[ m ] = parentFaceDirectionContainer[ m ]; + //} + + //½«´ËÐÂÉú³ÉµÄ¶Ô½Ó±ß½ç¼ÓÈë±¾¿éÀïÃæ + SplitBcPatch * patch = new SplitBcPatch(); + childInterfaceBc->patch = patch; + patch->splitZone = sourceZone; + + //patch->CopyVertexMappingContent( interfaceBc->GetZoneBoundaryConditionPatch()->GetVertexMapping() ); + + //vector< int > & pNextFaceDirectionContainer = interfaceBc->GetZoneBoundaryConditionPatch()->GetFaceDirectionContainer(); + //vector< int > & patchFaceDirectionContainer = patch->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // patchFaceDirectionContainer[ m ] = pNextFaceDirectionContainer[ m ]; + //} + + //Ô­¶Ô½Ó±ß½çÂú×ã + //t0 = tref + M * s0 + //еĶԽӱ߽çÂú×ã + //t0newblock + refNewblock = tref + M * s0 + //t0newblock = ( tref - refNewblock ) + M * s0 + + //È»ºó½øÐÐÐÞÕý + //for ( int m = 0; m < 3; ++ m ) + //{ + // ( patch->GetVertexMapping() )[ m ][ 3 ] -= ( sourceZone->GetOriginalPointIndexContainer() )[ m ]; + //} + + return true; +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateSplitBcFromOverlapRegion( parentSplitBc, overlapRegion ); + + //SplitBc * splitBc = new SplitBc(); + //this->AddSplitBc( splitBc ); + + //splitBc->SetRegion( overlapRegion ); + //splitBc->bcType = parentSplitBc->bcType; + //splitBc->splitZone = this; + //splitBc->ChangeRegionToLocalCoordinate(); + //splitBc->CreateInterfaceBcFromParentBc( parentSplitBc ); + int kkk = 1; + } + } + else + { + int nChilds = parentSplitBc->child->size(); + for ( int iChild = 0; iChild < nChilds; ++ iChild ) + { + this->CreateSplitBc( ( * parentSplitBc->child )[ iChild ] ); + } + } +} + +void SplitZone::CreateSplitBcFromOverlapRegion( SplitBc * parentSplitBc, RangeRegion & overlapRegion ) +{ + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + splitBc->ChangeRegionToLocalCoordinate(); + splitBc->CreateInterfaceBcFromParentBc( parentSplitBc ); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 3; + this->ReadGrid(); + this->Split(); + this->ModifyZoneIndex(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + SplitBc * splitBc = new SplitBc(); + splitBcList.push_back( splitBc ); + + ZoneBc * zoneBc = zone->bccos[ iBcRegion ]; + + splitBc->splitZone = splitZone; + splitBc->bcType = zoneBc->bcType; + splitBc->SetRegion( zoneBc->pnts ); + if ( zoneBc->patch ) + { + SplitBcPatch * patch = new SplitBcPatch(); + splitBc->patch = patch; + + patch->splitZone = refZone[ zoneBc->patch->donor_zoneid ]; + patch->SetRegion( zoneBc->patch->donor_pnts ); + } + } + + int kkk = 1; + } + int kkk = 1; +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + //this->SetZoneIndex(); +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParent( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParent( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ + //std::vector< ZoneBc * > leafZoneBc; + + //std::vector< ZoneBc * > & zoneBcList = splitZone->GetZoneBcList(); + + //for ( int i = 0; i < zoneBcList.size(); ++ i ) + //{ + // std::vector< ZoneBc * > cl = zoneBcList[ i ]->GetLeaves(); + // for ( int j = 0; j < cl.size(); ++ j ) + // { + // leafZoneBc.push_back( cl[ j ] ); + // } + //} + + //int nZoneBc = leafZoneBc.size(); + + //for ( int iZoneBc = 0; iZoneBc < nZoneBc; ++ iZoneBc ) + //{ + // ZoneBc * zoneBc = leafZoneBc[ iZoneBc ]; + // zoneBc->DumpBc(); + //} +} + +void Partition::DumpMultiBasePartitionedGridFile() +{ + int fileId = -1; + std::string filename = this->outName; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "Zone" + std::to_string( splitZone->zoneIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->zoneIndex; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::DumpPartitionedGridFile() +{ + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->newIndex; + int oldZoneIndex = splitBc->patch->splitZone->zoneIndex; + std::cout << "id = " << id << "\n"; + std::cout << "oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01b/Partition.h b/example/partition/struct/2d/stage1/01b/Partition.h new file mode 100644 index 00000000..ff83de0e --- /dev/null +++ b/example/partition/struct/2d/stage1/01b/Partition.h @@ -0,0 +1,188 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + int regionAxis = -1; + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + void SetRegion( std::vector &pnts ); + int ComputeRegionAxis(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void CreateInterfaceBcFromParentBc( SplitBc * parentSplitBc ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); +}; + + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + void CreateBcFromParent(); + void CreateSplitBcFromOverlapRegion( SplitBc * parentSplitBc, RangeRegion & overlapRegion ); + void CreateChildInterfaceBc( RangeRegion & targeRegionBox, SplitZone * sourceZone ); + bool CreateChildInterfaceBc( SplitBc * parentSplitBc, RangeRegion & targeRegionBox, SplitZone * sourceZone ); + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpMultiBasePartitionedGridFile(); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01b/README.txt b/example/partition/struct/2d/stage1/01b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01b/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01b/heat2d2blocks.cgns new file mode 100644 index 00000000..2ce29d4c Binary files /dev/null and b/example/partition/struct/2d/stage1/01b/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01b/main.cpp b/example/partition/struct/2d/stage1/01b/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01b/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01c/CMakeLists.txt b/example/partition/struct/2d/stage1/01c/CMakeLists.txt new file mode 100644 index 00000000..9fa577c8 --- /dev/null +++ b/example/partition/struct/2d/stage1/01c/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01c/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01c/CgnsGrid.cpp new file mode 100644 index 00000000..d287afcb --- /dev/null +++ b/example/partition/struct/2d/stage1/01c/CgnsGrid.cpp @@ -0,0 +1,345 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc->pnts.push_back( range[ i ] ); + } + + zonebc->zoneid = gZoneId; + zonebc->bcType = BCTypeUserDefined; + + ZoneBcPatch * patch = new ZoneBcPatch(); + zonebc->patch = patch; + + patch->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + patch->donor_pnts.push_back( donor_range[ i ] ); + } + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01c/CgnsGrid.h b/example/partition/struct/2d/stage1/01c/CgnsGrid.h new file mode 100644 index 00000000..af67a321 --- /dev/null +++ b/example/partition/struct/2d/stage1/01c/CgnsGrid.h @@ -0,0 +1,123 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01c/Partition.cpp b/example/partition/struct/2d/stage1/01c/Partition.cpp new file mode 100644 index 00000000..31b9ac1e --- /dev/null +++ b/example/partition/struct/2d/stage1/01c/Partition.cpp @@ -0,0 +1,1722 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + this->regionAxis = rhs.regionAxis; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } + this->ComputeRegionAxis(); +} + +int RangeRegion::ComputeRegionAxis() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] == this->end[ m ] ) + { + this->regionAxis = m; + return this->regionAxis; + } + } + return this->regionAxis; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + int kkk = 1; + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + SplitBc * splitBcL = new SplitBc(); + zoneL->AddSplitBc( splitBcL ); + + SplitBc * splitBcR = new SplitBc(); + zoneR->AddSplitBc( splitBcR ); + + splitBcL->splitZone = zoneL; + splitBcL->SetRegion( localInterfaceRegionL ); + splitBcL->bcType = BCTypeUserDefined; + + splitBcR->splitZone = zoneR; + splitBcR->SetRegion( localInterfaceRegionR ); + splitBcR->bcType = BCTypeUserDefined; + + //localInterfaceRegionL.MarkPatchBc(); + //localInterfaceRegionR.MarkPatchBc(); + + SplitBcPatch * splitBcPatchL = new SplitBcPatch(); + splitBcL->patch = splitBcPatchL; + splitBcPatchL->region = localInterfaceRegionR; + splitBcPatchL->splitZone = zoneR; + + SplitBcPatch * splitBcPatchR = new SplitBcPatch(); + splitBcR->patch = splitBcPatchR; + splitBcPatchR->region = localInterfaceRegionL; + splitBcPatchR->splitZone = zoneL; + + //splitBcL->Normalize(); + //splitBcR->Normalize(); +} + + +SplitBc::SplitBc() +{ + this->region.Init( Dim::dim ); +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::GetLeafBcs( std::vector< SplitBc * > & leafBcs ) +{ + if ( ! this->child ) + { + leafBcs.push_back( this ); + return; + } + + for ( int i = 0; i < this->child->size(); ++ i ) + { + std::vector< SplitBc * > child_leafBcs; + ( * child )[ i ]->GetLeafBcs( child_leafBcs ); + for ( int j = 0; j < child_leafBcs.size(); ++ j ) + { + leafBcs.push_back( child_leafBcs[ j ] ); + } + } + + return; +} + +void SplitBc::CreateInterfaceBcFromParentBcNewVersion( SplitBc * parentSplitBc ) +{ + if ( parentSplitBc->bcType != BCTypeUserDefined ) return; + + this->patch = new SplitBcPatch(); + this->patch->splitZone = parentSplitBc->patch->splitZone; + this->patch->SetRegion( parentSplitBc->patch->region ); + int kkk = 1; + + //Find the block corresponding to this docking boundary + //From patch->splitZone, find the corresponding docking boundary according to the size of overlapt + //The boundary conditions on the opposite side must change due to the split of this block. + //Here, the relevant boundaries are added to the sub-boundaries. + + RangeRegion targetRegionBox; + targetRegionBox = parentSplitBc->patch->region; + + SplitZone * targetZone = this->patch->splitZone; + + //targetZone->CreateChildInterfaceBc( targetRegionBox, this->splitZone ); + targetZone->CreateChildInterfaceBc( this ); + + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildInterfaceBc( tRangeBox, this->splitZone ); +} + +void SplitBc::CreateInterfaceBcFromParentBc( SplitBc * parentSplitBc ) +{ + if ( parentSplitBc->bcType != BCTypeUserDefined ) return; + + this->patch = new SplitBcPatch(); + this->patch->splitZone = parentSplitBc->patch->splitZone; + this->patch->SetRegion( parentSplitBc->patch->region ); + int kkk = 1; + + //Find the block corresponding to this docking boundary + //From patch->splitZone, find the corresponding docking boundary according to the size of overlapt + //The boundary conditions on the opposite side must change due to the split of this block. + //Here, the relevant boundaries are added to the sub-boundaries. + + RangeRegion targetRegionBox; + targetRegionBox = parentSplitBc->patch->region; + + SplitZone * targetZone = this->patch->splitZone; + + targetZone->CreateChildInterfaceBc( targetRegionBox, this->splitZone ); + + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildInterfaceBc( tRangeBox, this->splitZone ); +} + + +SplitBcPatch::SplitBcPatch() +{ + this->region.Init( Dim::dim ); +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +void SplitBcPatch::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBcPatch::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::GetLeafBcList( std::vector< SplitBc * > & leafBcList ) +{ + int nSplitBcs = this->splitBcList.size(); + + for ( int iSplitBcs = 0; iSplitBcs < nSplitBcs; ++ iSplitBcs ) + { + SplitBc * splitBc = splitBcList[ iSplitBcs ]; + + std::vector< SplitBc * > leafBcs; + splitBc->GetLeafBcs( leafBcs ); + for ( int j = 0; j < leafBcs.size(); ++ j ) + { + leafBcList.push_back( leafBcs[ j ] ); + } + } +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + std::vector< SplitBc * > & parentSplitBcList = this->parent->GetSplitBcList(); + + int nParentSplitBcs = parentSplitBcList.size(); + + for ( int iParentBc = 0; iParentBc < nParentSplitBcs; ++ iParentBc ) + { + SplitBc * parentSplitBc = parentSplitBcList[ iParentBc ]; + + this->CreateSplitBc( parentSplitBc ); + } +} + +void SplitZone::CreateChildInterfaceBc( SplitBc * targetInterfaceBc ) +{ + std::vector< SplitBc * > & splitBcList = this->GetSplitBcList(); + + int nSplitBcs = splitBcList.size(); + + for ( int iSplitBc = 0; iSplitBc < nSplitBcs; ++ iSplitBc ) + { + SplitBc * splitBc = splitBcList[ iSplitBc ]; + + //Only consider the interface boundaries + if ( splitBc->bcType != BCTypeUserDefined ) continue; + SplitBc * candidateInterfaceBc = splitBc; + + if ( this->CreateChildInterfaceBc( candidateInterfaceBc, targetInterfaceBc ) ) + { + return; + } + } +} + +bool SplitZone::CreateChildInterfaceBc( SplitBc * candidateInterfaceBc, SplitBc * targetInterfaceBc ) +{ + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( candidateInterfaceBc->region, targetInterfaceBc->patch->region, overlapRegion ); + if ( ! overlap_flag ) return false; + + //1. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬µ«ÊÇinterfaceBcûÓÐchild£¬Ôò´ËsplitBc×÷ΪinterfaceBcµÄÒ»¸öchild + //2. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍËùÓÐchildûÓн»¼¯£¬ + // ÔòsplitBc¼ÓÈëinterfaceBcµÄÒ»¸öchild + //3. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍchildÓн»¼¯£¬Ôò´Ëchild×÷ΪеÄinterfaceBc + + std::vector< SplitBc * > * child = candidateInterfaceBc->child; + + if ( candidateInterfaceBc->child ) + { + for ( int iChild = 0; iChild < candidateInterfaceBc->child->size(); ++ iChild ) + { + SplitBc * childSplitBc = ( * candidateInterfaceBc->child )[ iChild ]; + if ( this->CreateChildInterfaceBc( childSplitBc, targetInterfaceBc ) ) return true; + } + } + else + { + candidateInterfaceBc->child = new std::vector< SplitBc * >(); + } + + SplitBc * childInterfaceBc = new SplitBc(); + + childInterfaceBc->SetRegion( overlapRegion ); + childInterfaceBc->bcType = candidateInterfaceBc->bcType; + childInterfaceBc->splitZone = candidateInterfaceBc->splitZone; + + candidateInterfaceBc->child->push_back( childInterfaceBc ); + + //vector< int > & parentFaceDirectionContainer = interfaceBc->GetFaceDirectionContainer(); + //vector< int > & faceDirectionContainer = childInterfaceBc->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // faceDirectionContainer[ m ] = parentFaceDirectionContainer[ m ]; + //} + + //½«´ËÐÂÉú³ÉµÄ¶Ô½Ó±ß½ç¼ÓÈë±¾¿éÀïÃæ + SplitBcPatch * patch = new SplitBcPatch(); + childInterfaceBc->patch = patch; + patch->splitZone = targetInterfaceBc->splitZone; + patch->region = targetInterfaceBc->region; + + //patch->CopyVertexMappingContent( interfaceBc->GetZoneBoundaryConditionPatch()->GetVertexMapping() ); + + //vector< int > & pNextFaceDirectionContainer = interfaceBc->GetZoneBoundaryConditionPatch()->GetFaceDirectionContainer(); + //vector< int > & patchFaceDirectionContainer = patch->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // patchFaceDirectionContainer[ m ] = pNextFaceDirectionContainer[ m ]; + //} + + //Ô­¶Ô½Ó±ß½çÂú×ã + //t0 = tref + M * s0 + //еĶԽӱ߽çÂú×ã + //t0newblock + refNewblock = tref + M * s0 + //t0newblock = ( tref - refNewblock ) + M * s0 + + //È»ºó½øÐÐÐÞÕý + //for ( int m = 0; m < 3; ++ m ) + //{ + // ( patch->GetVertexMapping() )[ m ][ 3 ] -= ( sourceZone->GetOriginalPointIndexContainer() )[ m ]; + //} + + return true; +} + +void SplitZone::CreateChildInterfaceBc( RangeRegion &targeRegionBox, SplitZone * sourceZone ) +{ + std::vector< SplitBc * > & splitBcList = this->GetSplitBcList(); + + int nSplitBcs = splitBcList.size(); + + for ( int iSplitBc = 0; iSplitBc < nSplitBcs; ++ iSplitBc ) + { + SplitBc * splitBc = splitBcList[ iSplitBc ]; + + //Only consider the interface boundaries + if ( splitBc->bcType != BCTypeUserDefined ) continue; + + if ( this->CreateChildInterfaceBc( splitBc, targeRegionBox, sourceZone ) ) return; + } +} + +bool SplitZone::CreateChildInterfaceBc( SplitBc * interfaceBc, RangeRegion & targeRegionBox, SplitZone * sourceZone ) +{ + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( interfaceBc->region, targeRegionBox, overlapRegion ); + if ( ! overlap_flag ) return false; + + //1. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬µ«ÊÇinterfaceBcûÓÐchild£¬Ôò´ËsplitBc×÷ΪinterfaceBcµÄÒ»¸öchild + //2. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍËùÓÐchildûÓн»¼¯£¬ + // ÔòsplitBc¼ÓÈëinterfaceBcµÄÒ»¸öchild + //3. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍchildÓн»¼¯£¬Ôò´Ëchild×÷ΪеÄinterfaceBc + + std::vector< SplitBc * > * child = interfaceBc->child; + + if ( interfaceBc->child ) + { + for ( int iChild = 0; iChild < interfaceBc->child->size(); ++ iChild ) + { + SplitBc * childSplitBc = ( * interfaceBc->child )[ iChild ]; + if ( this->CreateChildInterfaceBc( childSplitBc, targeRegionBox, sourceZone ) ) return true; + } + } + else + { + interfaceBc->child = new std::vector< SplitBc * >(); + } + + SplitBc * childInterfaceBc = new SplitBc(); + //this->AddSplitBc( splitBc ); + + childInterfaceBc->SetRegion( overlapRegion ); + childInterfaceBc->bcType = interfaceBc->bcType; + childInterfaceBc->splitZone = interfaceBc->splitZone; + + + interfaceBc->child->push_back( childInterfaceBc ); + + //vector< int > & parentFaceDirectionContainer = interfaceBc->GetFaceDirectionContainer(); + //vector< int > & faceDirectionContainer = childInterfaceBc->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // faceDirectionContainer[ m ] = parentFaceDirectionContainer[ m ]; + //} + + //½«´ËÐÂÉú³ÉµÄ¶Ô½Ó±ß½ç¼ÓÈë±¾¿éÀïÃæ + SplitBcPatch * patch = new SplitBcPatch(); + childInterfaceBc->patch = patch; + patch->splitZone = sourceZone; + + //patch->CopyVertexMappingContent( interfaceBc->GetZoneBoundaryConditionPatch()->GetVertexMapping() ); + + //vector< int > & pNextFaceDirectionContainer = interfaceBc->GetZoneBoundaryConditionPatch()->GetFaceDirectionContainer(); + //vector< int > & patchFaceDirectionContainer = patch->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // patchFaceDirectionContainer[ m ] = pNextFaceDirectionContainer[ m ]; + //} + + //Ô­¶Ô½Ó±ß½çÂú×ã + //t0 = tref + M * s0 + //еĶԽӱ߽çÂú×ã + //t0newblock + refNewblock = tref + M * s0 + //t0newblock = ( tref - refNewblock ) + M * s0 + + //È»ºó½øÐÐÐÞÕý + //for ( int m = 0; m < 3; ++ m ) + //{ + // ( patch->GetVertexMapping() )[ m ][ 3 ] -= ( sourceZone->GetOriginalPointIndexContainer() )[ m ]; + //} + + return true; +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateSplitBcFromOverlapRegion( parentSplitBc, overlapRegion ); + + int kkk = 1; + } + } + else + { + int nChilds = parentSplitBc->child->size(); + for ( int iChild = 0; iChild < nChilds; ++ iChild ) + { + this->CreateSplitBc( ( * parentSplitBc->child )[ iChild ] ); + } + } +} + +void SplitZone::CreateSplitBcFromOverlapRegion( SplitBc * parentSplitBc, RangeRegion & overlapRegion ) +{ + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + splitBc->ChangeRegionToLocalCoordinate(); + //splitBc->CreateInterfaceBcFromParentBc( parentSplitBc ); + splitBc->CreateInterfaceBcFromParentBcNewVersion( parentSplitBc ); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 3; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + SplitBc * splitBc = new SplitBc(); + splitBcList.push_back( splitBc ); + + ZoneBc * zoneBc = zone->bccos[ iBcRegion ]; + + splitBc->splitZone = splitZone; + splitBc->bcType = zoneBc->bcType; + splitBc->SetRegion( zoneBc->pnts ); + if ( zoneBc->patch ) + { + SplitBcPatch * patch = new SplitBcPatch(); + splitBc->patch = patch; + + patch->splitZone = refZone[ zoneBc->patch->donor_zoneid ]; + patch->SetRegion( zoneBc->patch->donor_pnts ); + } + } + + int kkk = 1; + } + int kkk = 1; +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParent( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParent( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpMultiBasePartitionedGridFile() +{ + int fileId = -1; + std::string filename = this->outName; + cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + std::string basename = "Base" + std::to_string( iProc ); + + int baseId = -1; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::string zonename = "Zone" + std::to_string( splitZone->zoneIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + int nBcLists = splitZone->splitBcList.size(); + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nBcLists; ++ ibc ) + { + SplitBc * splitBc = splitZone->splitBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->zoneIndex; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + //int nBcLists = splitZone->splitBcList.size(); + std::vector< SplitBc * > leafBcList; + splitZone->GetLeafBcList( leafBcList ); + int nLeafBcList = leafBcList.size(); + + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nLeafBcList; ++ ibc ) + { + SplitBc * splitBc = leafBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->newIndex; + int oldZoneIndex = splitBc->patch->splitZone->zoneIndex; + std::cout << "id = " << id << "\n"; + std::cout << "oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01c/Partition.h b/example/partition/struct/2d/stage1/01c/Partition.h new file mode 100644 index 00000000..2d976fd2 --- /dev/null +++ b/example/partition/struct/2d/stage1/01c/Partition.h @@ -0,0 +1,194 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + int regionAxis = -1; + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + void SetRegion( std::vector &pnts ); + int ComputeRegionAxis(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void CreateInterfaceBcFromParentBc( SplitBc * parentSplitBc ); + void CreateInterfaceBcFromParentBcNewVersion( SplitBc * parentSplitBc ); + void GetLeafBcs( std::vector< SplitBc * > & leafBcs ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); +}; + + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + void CreateBcFromParent(); + void CreateSplitBcFromOverlapRegion( SplitBc * parentSplitBc, RangeRegion & overlapRegion ); + void CreateChildInterfaceBc( SplitBc * targetInterfaceBc ); + bool CreateChildInterfaceBc( SplitBc * candidateInterfaceBc, SplitBc * targetInterfaceBc ); + + void CreateChildInterfaceBc( RangeRegion & targeRegionBox, SplitZone * sourceZone ); + bool CreateChildInterfaceBc( SplitBc * parentSplitBc, RangeRegion & targeRegionBox, SplitZone * sourceZone ); + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); + void GetLeafBcList( std::vector< SplitBc * > & leafBcList ); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpMultiBasePartitionedGridFile(); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01c/README.txt b/example/partition/struct/2d/stage1/01c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01c/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01c/heat2d2blocks.cgns new file mode 100644 index 00000000..2ce29d4c Binary files /dev/null and b/example/partition/struct/2d/stage1/01c/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01c/heat2dpart.cgns b/example/partition/struct/2d/stage1/01c/heat2dpart.cgns new file mode 100644 index 00000000..6351f809 Binary files /dev/null and b/example/partition/struct/2d/stage1/01c/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage1/01c/main.cpp b/example/partition/struct/2d/stage1/01c/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01c/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01d/CMakeLists.txt b/example/partition/struct/2d/stage1/01d/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage1/01d/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01d/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01d/CgnsGrid.cpp new file mode 100644 index 00000000..d287afcb --- /dev/null +++ b/example/partition/struct/2d/stage1/01d/CgnsGrid.cpp @@ -0,0 +1,345 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc->pnts.push_back( range[ i ] ); + } + + zonebc->zoneid = gZoneId; + zonebc->bcType = BCTypeUserDefined; + + ZoneBcPatch * patch = new ZoneBcPatch(); + zonebc->patch = patch; + + patch->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + patch->donor_pnts.push_back( donor_range[ i ] ); + } + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01d/CgnsGrid.h b/example/partition/struct/2d/stage1/01d/CgnsGrid.h new file mode 100644 index 00000000..af67a321 --- /dev/null +++ b/example/partition/struct/2d/stage1/01d/CgnsGrid.h @@ -0,0 +1,123 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + +class ZoneBc; + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01d/Partition.cpp b/example/partition/struct/2d/stage1/01d/Partition.cpp new file mode 100644 index 00000000..4d2bcf39 --- /dev/null +++ b/example/partition/struct/2d/stage1/01d/Partition.cpp @@ -0,0 +1,610 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nBcRegion = zone->bccos.size(); + std::cout << "nBcRegion = " << nBcRegion << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int iBcRegion = 0; iBcRegion < nBcRegion; ++ iBcRegion ) + { + SplitBc * splitBc = new SplitBc(); + splitBcList.push_back( splitBc ); + + ZoneBc * zoneBc = zone->bccos[ iBcRegion ]; + + splitBc->splitZone = splitZone; + splitBc->bcType = zoneBc->bcType; + splitBc->SetRegion( zoneBc->pnts ); + if ( zoneBc->patch ) + { + SplitBcPatch * patch = new SplitBcPatch(); + splitBc->patch = patch; + + patch->splitZone = refZone[ zoneBc->patch->donor_zoneid ]; + patch->SetRegion( zoneBc->patch->donor_pnts ); + } + } + + int kkk = 1; + } + int kkk = 1; +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParent( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParent( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + //int nBcLists = splitZone->splitBcList.size(); + std::vector< SplitBc * > leafBcList; + splitZone->GetLeafBcList( leafBcList ); + int nLeafBcList = leafBcList.size(); + + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nLeafBcList; ++ ibc ) + { + SplitBc * splitBc = leafBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->newIndex; + int oldZoneIndex = splitBc->patch->splitZone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01d/Partition.h b/example/partition/struct/2d/stage1/01d/Partition.h new file mode 100644 index 00000000..257548f7 --- /dev/null +++ b/example/partition/struct/2d/stage1/01d/Partition.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01d/README.txt b/example/partition/struct/2d/stage1/01d/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01d/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01d/SplitZone.cpp b/example/partition/struct/2d/stage1/01d/SplitZone.cpp new file mode 100644 index 00000000..707c66b2 --- /dev/null +++ b/example/partition/struct/2d/stage1/01d/SplitZone.cpp @@ -0,0 +1,804 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + this->regionAxis = rhs.regionAxis; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } + this->ComputeRegionAxis(); +} + +int RangeRegion::ComputeRegionAxis() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] == this->end[ m ] ) + { + this->regionAxis = m; + return this->regionAxis; + } + } + return this->regionAxis; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + int kkk = 1; + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + SplitBc * splitBcL = new SplitBc(); + zoneL->AddSplitBc( splitBcL ); + + SplitBc * splitBcR = new SplitBc(); + zoneR->AddSplitBc( splitBcR ); + + splitBcL->splitZone = zoneL; + splitBcL->SetRegion( localInterfaceRegionL ); + splitBcL->bcType = BCTypeUserDefined; + + splitBcR->splitZone = zoneR; + splitBcR->SetRegion( localInterfaceRegionR ); + splitBcR->bcType = BCTypeUserDefined; + + //localInterfaceRegionL.MarkPatchBc(); + //localInterfaceRegionR.MarkPatchBc(); + + SplitBcPatch * splitBcPatchL = new SplitBcPatch(); + splitBcL->patch = splitBcPatchL; + splitBcPatchL->region = localInterfaceRegionR; + splitBcPatchL->splitZone = zoneR; + + SplitBcPatch * splitBcPatchR = new SplitBcPatch(); + splitBcR->patch = splitBcPatchR; + splitBcPatchR->region = localInterfaceRegionL; + splitBcPatchR->splitZone = zoneL; + + //splitBcL->Normalize(); + //splitBcR->Normalize(); +} + + +SplitBc::SplitBc() +{ + this->region.Init( Dim::dim ); +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::GetLeafBcs( std::vector< SplitBc * > & leafBcs ) +{ + if ( ! this->child ) + { + leafBcs.push_back( this ); + return; + } + + for ( int i = 0; i < this->child->size(); ++ i ) + { + std::vector< SplitBc * > child_leafBcs; + ( * child )[ i ]->GetLeafBcs( child_leafBcs ); + for ( int j = 0; j < child_leafBcs.size(); ++ j ) + { + leafBcs.push_back( child_leafBcs[ j ] ); + } + } + + return; +} + +void SplitBc::CreateInterfaceBcFromParentBcNewVersion( SplitBc * parentSplitBc ) +{ + if ( parentSplitBc->bcType != BCTypeUserDefined ) return; + + this->patch = new SplitBcPatch(); + this->patch->splitZone = parentSplitBc->patch->splitZone; + this->patch->SetRegion( parentSplitBc->patch->region ); + int kkk = 1; + + //Find the block corresponding to this docking boundary + //From patch->splitZone, find the corresponding docking boundary according to the size of overlapt + //The boundary conditions on the opposite side must change due to the split of this block. + //Here, the relevant boundaries are added to the sub-boundaries. + + RangeRegion targetRegionBox; + targetRegionBox = parentSplitBc->patch->region; + + SplitZone * targetZone = this->patch->splitZone; + + targetZone->CreateChildInterfaceBc( this ); + + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildInterfaceBc( tRangeBox, this->splitZone ); +} + +SplitBcPatch::SplitBcPatch() +{ + this->region.Init( Dim::dim ); +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +void SplitBcPatch::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBcPatch::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::GetLeafBcList( std::vector< SplitBc * > & leafBcList ) +{ + int nSplitBcs = this->splitBcList.size(); + + for ( int iSplitBcs = 0; iSplitBcs < nSplitBcs; ++ iSplitBcs ) + { + SplitBc * splitBc = splitBcList[ iSplitBcs ]; + + std::vector< SplitBc * > leafBcs; + splitBc->GetLeafBcs( leafBcs ); + for ( int j = 0; j < leafBcs.size(); ++ j ) + { + leafBcList.push_back( leafBcs[ j ] ); + } + } +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + std::vector< SplitBc * > & parentSplitBcList = this->parent->GetSplitBcList(); + + int nParentSplitBcs = parentSplitBcList.size(); + + for ( int iParentBc = 0; iParentBc < nParentSplitBcs; ++ iParentBc ) + { + SplitBc * parentSplitBc = parentSplitBcList[ iParentBc ]; + + this->CreateSplitBc( parentSplitBc ); + } + int kkk = 1; +} + +void SplitZone::CreateChildInterfaceBc( SplitBc * targetInterfaceBc ) +{ + std::vector< SplitBc * > & splitBcList = this->GetSplitBcList(); + + int nSplitBcs = splitBcList.size(); + + for ( int iSplitBc = 0; iSplitBc < nSplitBcs; ++ iSplitBc ) + { + SplitBc * splitBc = splitBcList[ iSplitBc ]; + + //Only consider the interface boundaries + if ( splitBc->bcType != BCTypeUserDefined ) continue; + SplitBc * candidateInterfaceBc = splitBc; + + if ( this->CreateChildInterfaceBc( candidateInterfaceBc, targetInterfaceBc ) ) + { + return; + } + } +} + +bool SplitZone::CreateChildInterfaceBc( SplitBc * candidateInterfaceBc, SplitBc * targetInterfaceBc ) +{ + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( candidateInterfaceBc->region, targetInterfaceBc->patch->region, overlapRegion ); + if ( ! overlap_flag ) return false; + + //1. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬µ«ÊÇinterfaceBcûÓÐchild£¬Ôò´ËsplitBc×÷ΪinterfaceBcµÄÒ»¸öchild + //2. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍËùÓÐchildûÓн»¼¯£¬ + // ÔòsplitBc¼ÓÈëinterfaceBcµÄÒ»¸öchild + //3. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍchildÓн»¼¯£¬Ôò´Ëchild×÷ΪеÄinterfaceBc + + std::vector< SplitBc * > * child = candidateInterfaceBc->child; + + if ( candidateInterfaceBc->child ) + { + for ( int iChild = 0; iChild < candidateInterfaceBc->child->size(); ++ iChild ) + { + SplitBc * childSplitBc = ( * candidateInterfaceBc->child )[ iChild ]; + if ( this->CreateChildInterfaceBc( childSplitBc, targetInterfaceBc ) ) return true; + } + } + else + { + candidateInterfaceBc->child = new std::vector< SplitBc * >(); + } + + SplitBc * childInterfaceBc = new SplitBc(); + + childInterfaceBc->SetRegion( overlapRegion ); + childInterfaceBc->bcType = candidateInterfaceBc->bcType; + childInterfaceBc->splitZone = candidateInterfaceBc->splitZone; + + candidateInterfaceBc->child->push_back( childInterfaceBc ); + + //vector< int > & parentFaceDirectionContainer = interfaceBc->GetFaceDirectionContainer(); + //vector< int > & faceDirectionContainer = childInterfaceBc->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // faceDirectionContainer[ m ] = parentFaceDirectionContainer[ m ]; + //} + + //½«´ËÐÂÉú³ÉµÄ¶Ô½Ó±ß½ç¼ÓÈë±¾¿éÀïÃæ + SplitBcPatch * patch = new SplitBcPatch(); + childInterfaceBc->patch = patch; + patch->splitZone = targetInterfaceBc->splitZone; + patch->region = targetInterfaceBc->region; + + //patch->CopyVertexMappingContent( interfaceBc->GetZoneBoundaryConditionPatch()->GetVertexMapping() ); + + //vector< int > & pNextFaceDirectionContainer = interfaceBc->GetZoneBoundaryConditionPatch()->GetFaceDirectionContainer(); + //vector< int > & patchFaceDirectionContainer = patch->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // patchFaceDirectionContainer[ m ] = pNextFaceDirectionContainer[ m ]; + //} + + //Ô­¶Ô½Ó±ß½çÂú×ã + //t0 = tref + M * s0 + //еĶԽӱ߽çÂú×ã + //t0newblock + refNewblock = tref + M * s0 + //t0newblock = ( tref - refNewblock ) + M * s0 + + //È»ºó½øÐÐÐÞÕý + //for ( int m = 0; m < 3; ++ m ) + //{ + // ( patch->GetVertexMapping() )[ m ][ 3 ] -= ( sourceZone->GetOriginalPointIndexContainer() )[ m ]; + //} + + return true; +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateSplitBcFromOverlapRegion( parentSplitBc, overlapRegion ); + + int kkk = 1; + } + } + else + { + int nChilds = parentSplitBc->child->size(); + for ( int iChild = 0; iChild < nChilds; ++ iChild ) + { + this->CreateSplitBc( ( * parentSplitBc->child )[ iChild ] ); + } + } +} + +void SplitZone::CreateSplitBcFromOverlapRegion( SplitBc * parentSplitBc, RangeRegion & overlapRegion ) +{ + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + splitBc->ChangeRegionToLocalCoordinate(); + //splitBc->CreateInterfaceBcFromParentBc( parentSplitBc ); + splitBc->CreateInterfaceBcFromParentBcNewVersion( parentSplitBc ); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage1/01d/SplitZone.h b/example/partition/struct/2d/stage1/01d/SplitZone.h new file mode 100644 index 00000000..7a2ed24b --- /dev/null +++ b/example/partition/struct/2d/stage1/01d/SplitZone.h @@ -0,0 +1,143 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + int regionAxis = -1; + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + void SetRegion( std::vector &pnts ); + int ComputeRegionAxis(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void CreateInterfaceBcFromParentBcNewVersion( SplitBc * parentSplitBc ); + void GetLeafBcs( std::vector< SplitBc * > & leafBcs ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); +}; + + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + void CreateBcFromParent(); + void CreateSplitBcFromOverlapRegion( SplitBc * parentSplitBc, RangeRegion & overlapRegion ); + void CreateChildInterfaceBc( SplitBc * targetInterfaceBc ); + bool CreateChildInterfaceBc( SplitBc * candidateInterfaceBc, SplitBc * targetInterfaceBc ); + + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); + void GetLeafBcList( std::vector< SplitBc * > & leafBcList ); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage1/01d/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01d/heat2d2blocks.cgns new file mode 100644 index 00000000..ab4dcea5 Binary files /dev/null and b/example/partition/struct/2d/stage1/01d/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01d/heat2dpart.cgns b/example/partition/struct/2d/stage1/01d/heat2dpart.cgns new file mode 100644 index 00000000..7d2865a0 Binary files /dev/null and b/example/partition/struct/2d/stage1/01d/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage1/01d/main.cpp b/example/partition/struct/2d/stage1/01d/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01d/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01e/CMakeLists.txt b/example/partition/struct/2d/stage1/01e/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage1/01e/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01e/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01e/CgnsGrid.cpp new file mode 100644 index 00000000..51872e02 --- /dev/null +++ b/example/partition/struct/2d/stage1/01e/CgnsGrid.cpp @@ -0,0 +1,365 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + //ZoneBc * zonebc = new ZoneBc(); + //zone->bccos.push_back( zonebc ); + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < range.size(); ++ i ) + { + //zonebc->pnts.push_back( range[ i ] ); + zonebc_1to1->pnts.push_back( range[ i ] ); + } + + zonebc_1to1->zoneid = gZoneId; + + //zonebc->zoneid = gZoneId; + //zonebc->bcType = BCTypeUserDefined; + + //ZoneBcPatch * patch = new ZoneBcPatch(); + //zonebc->patch = patch; + //patch->transform = transform; + //patch->donor_zoneid = gDonorZoneId; + + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + //patch->donor_pnts.push_back( donor_range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01e/CgnsGrid.h b/example/partition/struct/2d/stage1/01e/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage1/01e/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01e/Partition.cpp b/example/partition/struct/2d/stage1/01e/Partition.cpp new file mode 100644 index 00000000..c8dc64c4 --- /dev/null +++ b/example/partition/struct/2d/stage1/01e/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + //interfaceSplitBc->donor_bc + } + } + int kkk = 1; +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParent( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParent( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + //int nBcLists = splitZone->splitBcList.size(); + std::vector< SplitBc * > leafBcList; + splitZone->GetLeafBcList( leafBcList ); + int nLeafBcList = leafBcList.size(); + + std::vector bccoList; + std::vector bc1to1List; + + for ( int ibc = 0; ibc < nLeafBcList; ++ ibc ) + { + SplitBc * splitBc = leafBcList[ ibc ]; + if ( splitBc->bcType == BCTypeUserDefined ) + { + bc1to1List.push_back( splitBc ); + } + else + { + bccoList.push_back( splitBc ); + } + } + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + SplitBc * splitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + SplitBc * splitBc = bc1to1List[ i1to1 ]; + BCType_t bocotype = static_cast( splitBc->bcType ); + + std::vector pnts; + std::vector pntsdonor; + int nSize = splitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( splitBc->region.end[ i ] ); + } + + int nPatchSize = splitBc->patch->region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( splitBc->patch->region.end[ i ] ); + } + int id = splitBc->patch->splitZone->newIndex; + int oldZoneIndex = splitBc->patch->splitZone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01e/Partition.h b/example/partition/struct/2d/stage1/01e/Partition.h new file mode 100644 index 00000000..257548f7 --- /dev/null +++ b/example/partition/struct/2d/stage1/01e/Partition.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01e/README.txt b/example/partition/struct/2d/stage1/01e/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01e/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01e/SplitZone.cpp b/example/partition/struct/2d/stage1/01e/SplitZone.cpp new file mode 100644 index 00000000..5af6d830 --- /dev/null +++ b/example/partition/struct/2d/stage1/01e/SplitZone.cpp @@ -0,0 +1,1110 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + int kkk = 1; + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + SplitBc * splitBcL = new SplitBc(); + zoneL->AddSplitBc( splitBcL ); + + SplitBc * splitBcR = new SplitBc(); + zoneR->AddSplitBc( splitBcR ); + + splitBcL->splitZone = zoneL; + splitBcL->SetRegion( localInterfaceRegionL ); + splitBcL->bcType = BCTypeUserDefined; + + splitBcR->splitZone = zoneR; + splitBcR->SetRegion( localInterfaceRegionR ); + splitBcR->bcType = BCTypeUserDefined; + + //localInterfaceRegionL.MarkPatchBc(); + //localInterfaceRegionR.MarkPatchBc(); + + SplitBcPatch * splitBcPatchL = new SplitBcPatch(); + splitBcL->patch = splitBcPatchL; + splitBcPatchL->region = localInterfaceRegionR; + splitBcPatchL->splitZone = zoneR; + + SplitBcPatch * splitBcPatchR = new SplitBcPatch(); + splitBcR->patch = splitBcPatchR; + splitBcPatchR->region = localInterfaceRegionL; + splitBcPatchR->splitZone = zoneL; + + //splitBcL->Normalize(); + //splitBcR->Normalize(); +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +SplitBc::SplitBc() +{ + this->region.Init( Dim::dim ); +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::GetLeafBcs( std::vector< SplitBc * > & leafBcs ) +{ + if ( ! this->child ) + { + leafBcs.push_back( this ); + return; + } + + for ( int i = 0; i < this->child->size(); ++ i ) + { + std::vector< SplitBc * > child_leafBcs; + ( * child )[ i ]->GetLeafBcs( child_leafBcs ); + for ( int j = 0; j < child_leafBcs.size(); ++ j ) + { + leafBcs.push_back( child_leafBcs[ j ] ); + } + } + + return; +} + +void SplitBc::CreateInterfaceBcFromParentBc( SplitBc * parentSplitBc ) +{ + if ( parentSplitBc->bcType != BCTypeUserDefined ) return; + + this->patch = new SplitBcPatch(); + this->patch->splitZone = parentSplitBc->patch->splitZone; + this->patch->SetRegion( parentSplitBc->patch->region ); + int kkk = 1; + + //Find the block corresponding to this docking boundary + //From patch->splitZone, find the corresponding docking boundary according to the size of overlapt + //The boundary conditions on the opposite side must change due to the split of this block. + //Here, the relevant boundaries are added to the sub-boundaries. + + RangeRegion targetRegionBox; + targetRegionBox = parentSplitBc->patch->region; + + SplitZone * targetZone = this->patch->splitZone; + + targetZone->CreateChildInterfaceBc( this ); + + //this->patch->faceAxis = parentSplitBc->patch->faceAxis; + + //( * this->patch->vertexMap ) = ( * parentBc->patch->vertexMap ); + + ////È»ºó½øÐÐÐÞÕý + ////block1->map 1, 33 -> block1 369, 337 + ////block2->global -> map 1, 33 -> block1 369, 337 + ////block2->local -> map 1, 33 -> block1 369, 337 + ////refOld + M * stold = block1Startold + ////refOld + M * ( stnew + ref ) = block1Startold + ////refNew = refOld + M * ( ref ) + + //for ( int m = 0; m < 3; ++ m ) + //{ + // for ( int n = 0; n < 3; ++ n ) + // { + // this->patch->vertexMap->pt[ m ] += this->patch->vertexMap->vm[ m ][ n ] * ( this->splitZone->sdim->oriPoint )[ n ]; + // } + //} + + //RangeBox tRangeBox; + + //MappingPatchPoint( this->patch, this->rangeBox, tRangeBox ); + //tRangeBox.SetOrder(); + + ////ÕÒµ½ºÍ±¾¶Ô½Ó±ß½çÏà¶ÔÓ¦µÄ¿é + ////´Ópatch->splitZone°´ÕÕoverlapµÄ´óСÕÒµ½¶ÔÓ¦µÄ¶Ô½Ó±ß½ç£¬ÕâÑùÖÁÉÙ¿ÉÒÔÕÒµ½ + ////¶ÔÃæµÄ¶Ô½Ó±ß½çÌõ¼þÓÉÓÚ±¾¿éµÄsplit±ØÈ»Òª·¢Éú¸Ä±ä£¬ÕâÀォÏà¹Ø±ß½ç¼ÓÈë×ӱ߽ç + //this->patch->splitZone->CreateChildInterfaceBc( tRangeBox, this->splitZone ); +} + +SplitBcPatch::SplitBcPatch() +{ + this->region.Init( Dim::dim ); +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +void SplitBcPatch::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBcPatch::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + //this->left = new BasicSplitBc(); + //this->right = new BasicSplitBc(); + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ + //delete this->left; + //delete this->right; +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::RecalcDonorRegion() +{ +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::GetLeafBcList( std::vector< SplitBc * > & leafBcList ) +{ + int nSplitBcs = this->splitBcList.size(); + + for ( int iSplitBcs = 0; iSplitBcs < nSplitBcs; ++ iSplitBcs ) + { + SplitBc * splitBc = splitBcList[ iSplitBcs ]; + + std::vector< SplitBc * > leafBcs; + splitBc->GetLeafBcs( leafBcs ); + for ( int j = 0; j < leafBcs.size(); ++ j ) + { + leafBcList.push_back( leafBcs[ j ] ); + } + } +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->donor_zone = parentInterfaceSplitBc->donor_zone; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * splitZone = interfaceSplitBc->donor_zone; + //splitZone-> +} + +void SplitZone::CreateChildInterfaceBc( SplitBc * targetInterfaceBc ) +{ + std::vector< SplitBc * > & splitBcList = this->GetSplitBcList(); + + int nSplitBcs = splitBcList.size(); + + for ( int iSplitBc = 0; iSplitBc < nSplitBcs; ++ iSplitBc ) + { + SplitBc * splitBc = splitBcList[ iSplitBc ]; + + //Only consider the interface boundaries + if ( splitBc->bcType != BCTypeUserDefined ) continue; + SplitBc * candidateInterfaceBc = splitBc; + + if ( this->CreateChildInterfaceBc( candidateInterfaceBc, targetInterfaceBc ) ) + { + return; + } + } +} + +bool SplitZone::CreateChildInterfaceBc( SplitBc * candidateInterfaceBc, SplitBc * targetInterfaceBc ) +{ + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( candidateInterfaceBc->region, targetInterfaceBc->patch->region, overlapRegion ); + if ( ! overlap_flag ) return false; + + //1. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬µ«ÊÇinterfaceBcûÓÐchild£¬Ôò´ËsplitBc×÷ΪinterfaceBcµÄÒ»¸öchild + //2. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍËùÓÐchildûÓн»¼¯£¬ + // ÔòsplitBc¼ÓÈëinterfaceBcµÄÒ»¸öchild + //3. Èç¹ûsplitBcºÍinterfaceBcÓн»¼¯£¬ÇÒinterfaceBcÓÐchild£¬Èç¹ûsplitBcºÍchildÓн»¼¯£¬Ôò´Ëchild×÷ΪеÄinterfaceBc + + std::vector< SplitBc * > * child = candidateInterfaceBc->child; + + if ( candidateInterfaceBc->child ) + { + for ( int iChild = 0; iChild < candidateInterfaceBc->child->size(); ++ iChild ) + { + SplitBc * childSplitBc = ( * candidateInterfaceBc->child )[ iChild ]; + if ( this->CreateChildInterfaceBc( childSplitBc, targetInterfaceBc ) ) return true; + } + } + else + { + candidateInterfaceBc->child = new std::vector< SplitBc * >(); + } + + SplitBc * childInterfaceBc = new SplitBc(); + + childInterfaceBc->SetRegion( overlapRegion ); + childInterfaceBc->bcType = candidateInterfaceBc->bcType; + childInterfaceBc->splitZone = candidateInterfaceBc->splitZone; + + candidateInterfaceBc->child->push_back( childInterfaceBc ); + + //vector< int > & parentFaceDirectionContainer = interfaceBc->GetFaceDirectionContainer(); + //vector< int > & faceDirectionContainer = childInterfaceBc->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // faceDirectionContainer[ m ] = parentFaceDirectionContainer[ m ]; + //} + + //½«´ËÐÂÉú³ÉµÄ¶Ô½Ó±ß½ç¼ÓÈë±¾¿éÀïÃæ + SplitBcPatch * patch = new SplitBcPatch(); + childInterfaceBc->patch = patch; + patch->splitZone = targetInterfaceBc->splitZone; + patch->region = targetInterfaceBc->region; + + //patch->CopyVertexMappingContent( interfaceBc->GetZoneBoundaryConditionPatch()->GetVertexMapping() ); + + //vector< int > & pNextFaceDirectionContainer = interfaceBc->GetZoneBoundaryConditionPatch()->GetFaceDirectionContainer(); + //vector< int > & patchFaceDirectionContainer = patch->GetFaceDirectionContainer(); + + //for ( int m = 0; m < 3; ++ m ) + //{ + // patchFaceDirectionContainer[ m ] = pNextFaceDirectionContainer[ m ]; + //} + + //Ô­¶Ô½Ó±ß½çÂú×ã + //t0 = tref + M * s0 + //еĶԽӱ߽çÂú×ã + //t0newblock + refNewblock = tref + M * s0 + //t0newblock = ( tref - refNewblock ) + M * s0 + + //È»ºó½øÐÐÐÞÕý + //for ( int m = 0; m < 3; ++ m ) + //{ + // ( patch->GetVertexMapping() )[ m ][ 3 ] -= ( sourceZone->GetOriginalPointIndexContainer() )[ m ]; + //} + + return true; +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + +void SplitZone::CreateSplitBc( SplitBc * parentSplitBc ) +{ + if ( ! parentSplitBc->child ) + { + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateSplitBcFromOverlapRegion( parentSplitBc, overlapRegion ); + + int kkk = 1; + } + } + else + { + int nChilds = parentSplitBc->child->size(); + for ( int iChild = 0; iChild < nChilds; ++ iChild ) + { + this->CreateSplitBc( ( * parentSplitBc->child )[ iChild ] ); + } + } +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +void SplitZone::CreateSplitBcFromOverlapRegion( SplitBc * parentSplitBc, RangeRegion & overlapRegion ) +{ + SplitBc * splitBc = new SplitBc(); + this->AddSplitBc( splitBc ); + + splitBc->SetRegion( overlapRegion ); + splitBc->bcType = parentSplitBc->bcType; + splitBc->splitZone = this; + splitBc->ChangeRegionToLocalCoordinate(); + splitBc->CreateInterfaceBcFromParentBc( parentSplitBc ); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage1/01e/SplitZone.h b/example/partition/struct/2d/stage1/01e/SplitZone.h new file mode 100644 index 00000000..c71bf579 --- /dev/null +++ b/example/partition/struct/2d/stage1/01e/SplitZone.h @@ -0,0 +1,213 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + void SetRegion( std::vector &pnts ); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void CreateInterfaceBcFromParentBc( SplitBc * parentSplitBc ); + void GetLeafBcs( std::vector< SplitBc * > & leafBcs ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + //BasicSplitBc * left; + //BasicSplitBc * right; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void RecalcDonorRegion(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + void CreateSplitBcFromOverlapRegion( SplitBc * parentSplitBc, RangeRegion & overlapRegion ); + void CreateChildInterfaceBc( SplitBc * targetInterfaceBc ); + bool CreateChildInterfaceBc( SplitBc * candidateInterfaceBc, SplitBc * targetInterfaceBc ); + + void CreateSplitBc( SplitBc * parentSplitBc ); + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); + void GetLeafBcList( std::vector< SplitBc * > & leafBcList ); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage1/01e/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01e/heat2d2blocks.cgns new file mode 100644 index 00000000..ab4dcea5 Binary files /dev/null and b/example/partition/struct/2d/stage1/01e/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01e/main.cpp b/example/partition/struct/2d/stage1/01e/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01e/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01f/CMakeLists.txt b/example/partition/struct/2d/stage1/01f/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage1/01f/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01f/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01f/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage1/01f/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01f/CgnsGrid.h b/example/partition/struct/2d/stage1/01f/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage1/01f/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01f/Partition.cpp b/example/partition/struct/2d/stage1/01f/Partition.cpp new file mode 100644 index 00000000..0d400c1c --- /dev/null +++ b/example/partition/struct/2d/stage1/01f/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + std::vector< SplitBc * > & splitBcList = splitZone->splitBcList; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceSplitBc * donorInterface = interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc ); + interfaceSplitBc->donor_bc = donorInterface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParent( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParent( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< SplitBc * > leafBcList; + splitZone->GetLeafBcList( leafBcList ); + int nLeafBcList = leafBcList.size(); + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01f/Partition.h b/example/partition/struct/2d/stage1/01f/Partition.h new file mode 100644 index 00000000..257548f7 --- /dev/null +++ b/example/partition/struct/2d/stage1/01f/Partition.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01f/README.txt b/example/partition/struct/2d/stage1/01f/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01f/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01f/SplitZone.cpp b/example/partition/struct/2d/stage1/01f/SplitZone.cpp new file mode 100644 index 00000000..09356f6f --- /dev/null +++ b/example/partition/struct/2d/stage1/01f/SplitZone.cpp @@ -0,0 +1,998 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +SplitBc::SplitBc() +{ + this->region.Init( Dim::dim ); +} + +SplitBc::~SplitBc() +{ + delete this->patch; +} + +void SplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void SplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void SplitBc::GetLeafBcs( std::vector< SplitBc * > & leafBcs ) +{ + if ( ! this->child ) + { + leafBcs.push_back( this ); + return; + } + + for ( int i = 0; i < this->child->size(); ++ i ) + { + std::vector< SplitBc * > child_leafBcs; + ( * child )[ i ]->GetLeafBcs( child_leafBcs ); + for ( int j = 0; j < child_leafBcs.size(); ++ j ) + { + leafBcs.push_back( child_leafBcs[ j ] ); + } + } + + return; +} + +SplitBcPatch::SplitBcPatch() +{ + this->region.Init( Dim::dim ); +} + +SplitBcPatch::~SplitBcPatch() +{ +} + +void SplitBcPatch::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void SplitBcPatch::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +InterfaceSplitBc * SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + return candidateDonorBc; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + return donorBc; + } + } + } + return nullptr; +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::GetLeafBcList( std::vector< SplitBc * > & leafBcList ) +{ + int nSplitBcs = this->splitBcList.size(); + + for ( int iSplitBcs = 0; iSplitBcs < nSplitBcs; ++ iSplitBcs ) + { + SplitBc * splitBc = splitBcList[ iSplitBcs ]; + + std::vector< SplitBc * > leafBcs; + splitBc->GetLeafBcs( leafBcs ); + for ( int j = 0; j < leafBcs.size(); ++ j ) + { + leafBcList.push_back( leafBcs[ j ] ); + } + } +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->donor_zone = parentInterfaceSplitBc->donor_zone; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + interfaceSplitBc->donor_bc = donor_zone->FindDonorInterface( interfaceSplitBc ); + int kkk = 1; +} + +void SplitZone::AddSplitBc( SplitBc * splitBc ) +{ + if ( ! splitBc ) return; + this->splitBcList.push_back( splitBc ); +} + + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage1/01f/SplitZone.h b/example/partition/struct/2d/stage1/01f/SplitZone.h new file mode 100644 index 00000000..a78207bf --- /dev/null +++ b/example/partition/struct/2d/stage1/01f/SplitZone.h @@ -0,0 +1,212 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitBc +{ +public: + SplitBc(); + ~SplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; + SplitBcPatch * patch = nullptr; + std::vector< SplitBc * > * child = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +public: + void GetLeafBcs( std::vector< SplitBc * > & leafBcs ); +}; + +class SplitBcPatch +{ +public: + SplitBcPatch (); + ~SplitBcPatch(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; +public: + std::vector< SplitBc * > splitBcList; + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + std::vector< SplitBc * > & GetSplitBcList() { return this->splitBcList; }; + InterfaceSplitBc * FindDonorInterface( InterfaceSplitBc * interfaceSplitBc ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void AddSplitBc( SplitBc * splitBc ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); + void GetLeafBcList( std::vector< SplitBc * > & leafBcList ); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage1/01f/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01f/heat2d2blocks.cgns new file mode 100644 index 00000000..ab4dcea5 Binary files /dev/null and b/example/partition/struct/2d/stage1/01f/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01f/main.cpp b/example/partition/struct/2d/stage1/01f/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01f/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01g/CMakeLists.txt b/example/partition/struct/2d/stage1/01g/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage1/01g/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01g/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01g/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage1/01g/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01g/CgnsGrid.h b/example/partition/struct/2d/stage1/01g/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage1/01g/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01g/Partition.cpp b/example/partition/struct/2d/stage1/01g/Partition.cpp new file mode 100644 index 00000000..344fcb5b --- /dev/null +++ b/example/partition/struct/2d/stage1/01g/Partition.cpp @@ -0,0 +1,612 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParent( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceSplitBc * donorInterface = interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc ); + interfaceSplitBc->donor_bc = donorInterface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParent( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParent( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + int kkk = 1; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01g/Partition.h b/example/partition/struct/2d/stage1/01g/Partition.h new file mode 100644 index 00000000..257548f7 --- /dev/null +++ b/example/partition/struct/2d/stage1/01g/Partition.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone * > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01g/README.txt b/example/partition/struct/2d/stage1/01g/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01g/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01g/SplitZone.cpp b/example/partition/struct/2d/stage1/01g/SplitZone.cpp new file mode 100644 index 00000000..1168656d --- /dev/null +++ b/example/partition/struct/2d/stage1/01g/SplitZone.cpp @@ -0,0 +1,903 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +InterfaceSplitBc * SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + return candidateDonorBc; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + return donorBc; + } + } + } + return nullptr; +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->donor_zone = parentInterfaceSplitBc->donor_zone; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + interfaceSplitBc->donor_bc = donor_zone->FindDonorInterface( interfaceSplitBc ); + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage1/01g/SplitZone.h b/example/partition/struct/2d/stage1/01g/SplitZone.h new file mode 100644 index 00000000..4c7ae07c --- /dev/null +++ b/example/partition/struct/2d/stage1/01g/SplitZone.h @@ -0,0 +1,173 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + InterfaceSplitBc * FindDonorInterface( InterfaceSplitBc * interfaceSplitBc ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage1/01g/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01g/heat2d2blocks.cgns new file mode 100644 index 00000000..ab4dcea5 Binary files /dev/null and b/example/partition/struct/2d/stage1/01g/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01g/main.cpp b/example/partition/struct/2d/stage1/01g/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01g/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01h/CMakeLists.txt b/example/partition/struct/2d/stage1/01h/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage1/01h/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01h/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01h/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage1/01h/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01h/CgnsGrid.h b/example/partition/struct/2d/stage1/01h/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage1/01h/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01h/Partition.cpp b/example/partition/struct/2d/stage1/01h/Partition.cpp new file mode 100644 index 00000000..77a9fb3a --- /dev/null +++ b/example/partition/struct/2d/stage1/01h/Partition.cpp @@ -0,0 +1,616 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceSplitBc * donorInterface = interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc ); + interfaceSplitBc->donor_bc = donorInterface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01h/Partition.h b/example/partition/struct/2d/stage1/01h/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage1/01h/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01h/README.txt b/example/partition/struct/2d/stage1/01h/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01h/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01h/SplitZone.cpp b/example/partition/struct/2d/stage1/01h/SplitZone.cpp new file mode 100644 index 00000000..4f262fd7 --- /dev/null +++ b/example/partition/struct/2d/stage1/01h/SplitZone.cpp @@ -0,0 +1,1018 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::AddShift( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +InterfaceSplitBc * SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + return candidateDonorBc; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + return donorBc; + } + } + } + return nullptr; +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + subDonorRegion.Print(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.AddShift( sub_zone->dimInfo.oriPoint ); + if ( g_region == subDonorRegion ) + { + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << donor_zone->zoneIndex << "\n"; + if ( donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + else + { + interfaceSplitBc->donor_zone = donor_zone; + interfaceSplitBc->donor_bc = donor_zone->FindDonorInterface( interfaceSplitBc ); + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage1/01h/SplitZone.h b/example/partition/struct/2d/stage1/01h/SplitZone.h new file mode 100644 index 00000000..b76fb88b --- /dev/null +++ b/example/partition/struct/2d/stage1/01h/SplitZone.h @@ -0,0 +1,189 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void AddShift( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + InterfaceSplitBc * FindDonorInterface( InterfaceSplitBc * interfaceSplitBc ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage1/01h/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01h/heat2d2blocks.cgns new file mode 100644 index 00000000..ab4dcea5 Binary files /dev/null and b/example/partition/struct/2d/stage1/01h/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01h/main.cpp b/example/partition/struct/2d/stage1/01h/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01h/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01i/CMakeLists.txt b/example/partition/struct/2d/stage1/01i/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage1/01i/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01i/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01i/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage1/01i/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01i/CgnsGrid.h b/example/partition/struct/2d/stage1/01i/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage1/01i/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01i/Partition.cpp b/example/partition/struct/2d/stage1/01i/Partition.cpp new file mode 100644 index 00000000..28a6b9d9 --- /dev/null +++ b/example/partition/struct/2d/stage1/01i/Partition.cpp @@ -0,0 +1,617 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01i/Partition.h b/example/partition/struct/2d/stage1/01i/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage1/01i/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01i/README.txt b/example/partition/struct/2d/stage1/01i/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01i/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01i/SplitZone.cpp b/example/partition/struct/2d/stage1/01i/SplitZone.cpp new file mode 100644 index 00000000..25fea184 --- /dev/null +++ b/example/partition/struct/2d/stage1/01i/SplitZone.cpp @@ -0,0 +1,1046 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::AddShift( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +InterfaceSplitBc * SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return candidateDonorBc; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return donorBc; + } + } + } + return nullptr; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + subDonorRegion.Print(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.AddShift( sub_zone->dimInfo.oriPoint ); + if ( g_region == subDonorRegion ) + { + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = interfaceSplitBc->region; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + //if ( donor_bc->donor_zone->zoneIndex == interfaceSplitBc->zone->zoneIndex ) + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + donor_bc->donor_zone = interfaceSplitBc->zone; + donor_bc->donor_region = interfaceSplitBc->region; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage1/01i/SplitZone.h b/example/partition/struct/2d/stage1/01i/SplitZone.h new file mode 100644 index 00000000..d387037e --- /dev/null +++ b/example/partition/struct/2d/stage1/01i/SplitZone.h @@ -0,0 +1,193 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void AddShift( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + InterfaceSplitBc * FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage1/01i/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01i/heat2d2blocks.cgns new file mode 100644 index 00000000..ab4dcea5 Binary files /dev/null and b/example/partition/struct/2d/stage1/01i/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01i/main.cpp b/example/partition/struct/2d/stage1/01i/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01i/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage1/01j/CMakeLists.txt b/example/partition/struct/2d/stage1/01j/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage1/01j/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage1/01j/CgnsGrid.cpp b/example/partition/struct/2d/stage1/01j/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage1/01j/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01j/CgnsGrid.h b/example/partition/struct/2d/stage1/01j/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage1/01j/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01j/Partition.cpp b/example/partition/struct/2d/stage1/01j/Partition.cpp new file mode 100644 index 00000000..86d4c39f --- /dev/null +++ b/example/partition/struct/2d/stage1/01j/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocks.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage1/01j/Partition.h b/example/partition/struct/2d/stage1/01j/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage1/01j/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage1/01j/README.txt b/example/partition/struct/2d/stage1/01j/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage1/01j/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage1/01j/SplitZone.cpp b/example/partition/struct/2d/stage1/01j/SplitZone.cpp new file mode 100644 index 00000000..633d4cf5 --- /dev/null +++ b/example/partition/struct/2d/stage1/01j/SplitZone.cpp @@ -0,0 +1,1046 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::AddShift( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + subDonorRegion.Print(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.AddShift( sub_zone->dimInfo.oriPoint ); + if ( g_region == subDonorRegion ) + { + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = interfaceSplitBc->region; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + //if ( donor_bc->donor_zone->zoneIndex == interfaceSplitBc->zone->zoneIndex ) + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + donor_bc->donor_zone = interfaceSplitBc->zone; + donor_bc->donor_region = interfaceSplitBc->region; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage1/01j/SplitZone.h b/example/partition/struct/2d/stage1/01j/SplitZone.h new file mode 100644 index 00000000..8e312dd2 --- /dev/null +++ b/example/partition/struct/2d/stage1/01j/SplitZone.h @@ -0,0 +1,193 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void AddShift( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage1/01j/heat2d2blocks.cgns b/example/partition/struct/2d/stage1/01j/heat2d2blocks.cgns new file mode 100644 index 00000000..ab4dcea5 Binary files /dev/null and b/example/partition/struct/2d/stage1/01j/heat2d2blocks.cgns differ diff --git a/example/partition/struct/2d/stage1/01j/heat2dpart.cgns b/example/partition/struct/2d/stage1/01j/heat2dpart.cgns new file mode 100644 index 00000000..3e2c9e62 Binary files /dev/null and b/example/partition/struct/2d/stage1/01j/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage1/01j/main.cpp b/example/partition/struct/2d/stage1/01j/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage1/01j/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage2/01/CMakeLists.txt b/example/partition/struct/2d/stage2/01/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage2/01/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage2/01/CgnsGrid.cpp b/example/partition/struct/2d/stage2/01/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage2/01/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01/CgnsGrid.h b/example/partition/struct/2d/stage2/01/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage2/01/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01/Partition.cpp b/example/partition/struct/2d/stage2/01/Partition.cpp new file mode 100644 index 00000000..70532641 --- /dev/null +++ b/example/partition/struct/2d/stage2/01/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocksv1.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01/Partition.h b/example/partition/struct/2d/stage2/01/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage2/01/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage2/01/README.txt b/example/partition/struct/2d/stage2/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage2/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage2/01/SplitZone.cpp b/example/partition/struct/2d/stage2/01/SplitZone.cpp new file mode 100644 index 00000000..633d4cf5 --- /dev/null +++ b/example/partition/struct/2d/stage2/01/SplitZone.cpp @@ -0,0 +1,1046 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::AddShift( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + subDonorRegion.Print(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.AddShift( sub_zone->dimInfo.oriPoint ); + if ( g_region == subDonorRegion ) + { + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = interfaceSplitBc->region; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + //if ( donor_bc->donor_zone->zoneIndex == interfaceSplitBc->zone->zoneIndex ) + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + donor_bc->donor_zone = interfaceSplitBc->zone; + donor_bc->donor_region = interfaceSplitBc->region; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage2/01/SplitZone.h b/example/partition/struct/2d/stage2/01/SplitZone.h new file mode 100644 index 00000000..8e312dd2 --- /dev/null +++ b/example/partition/struct/2d/stage2/01/SplitZone.h @@ -0,0 +1,193 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void AddShift( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage2/01/heat2d2blocksv1.cgns b/example/partition/struct/2d/stage2/01/heat2d2blocksv1.cgns new file mode 100644 index 00000000..2e1e69ca Binary files /dev/null and b/example/partition/struct/2d/stage2/01/heat2d2blocksv1.cgns differ diff --git a/example/partition/struct/2d/stage2/01/heat2dpart.cgns b/example/partition/struct/2d/stage2/01/heat2dpart.cgns new file mode 100644 index 00000000..f61ec4a2 Binary files /dev/null and b/example/partition/struct/2d/stage2/01/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage2/01/main.cpp b/example/partition/struct/2d/stage2/01/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage2/01/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage2/01a/CMakeLists.txt b/example/partition/struct/2d/stage2/01a/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage2/01a/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage2/01a/CgnsGrid.cpp b/example/partition/struct/2d/stage2/01a/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage2/01a/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01a/CgnsGrid.h b/example/partition/struct/2d/stage2/01a/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage2/01a/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01a/Partition.cpp b/example/partition/struct/2d/stage2/01a/Partition.cpp new file mode 100644 index 00000000..913d4f9c --- /dev/null +++ b/example/partition/struct/2d/stage2/01a/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocksv2.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01a/Partition.h b/example/partition/struct/2d/stage2/01a/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage2/01a/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage2/01a/README.txt b/example/partition/struct/2d/stage2/01a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage2/01a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage2/01a/SplitZone.cpp b/example/partition/struct/2d/stage2/01a/SplitZone.cpp new file mode 100644 index 00000000..e7ffa1b3 --- /dev/null +++ b/example/partition/struct/2d/stage2/01a/SplitZone.cpp @@ -0,0 +1,1065 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage2/01a/SplitZone.h b/example/partition/struct/2d/stage2/01a/SplitZone.h new file mode 100644 index 00000000..6ba99614 --- /dev/null +++ b/example/partition/struct/2d/stage2/01a/SplitZone.h @@ -0,0 +1,194 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage2/01a/heat2d2blocksv2.cgns b/example/partition/struct/2d/stage2/01a/heat2d2blocksv2.cgns new file mode 100644 index 00000000..c4af0d29 Binary files /dev/null and b/example/partition/struct/2d/stage2/01a/heat2d2blocksv2.cgns differ diff --git a/example/partition/struct/2d/stage2/01a/main.cpp b/example/partition/struct/2d/stage2/01a/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage2/01a/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage2/01b/CMakeLists.txt b/example/partition/struct/2d/stage2/01b/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage2/01b/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage2/01b/CgnsGrid.cpp b/example/partition/struct/2d/stage2/01b/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage2/01b/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01b/CgnsGrid.h b/example/partition/struct/2d/stage2/01b/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage2/01b/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01b/Partition.cpp b/example/partition/struct/2d/stage2/01b/Partition.cpp new file mode 100644 index 00000000..320fe4e5 --- /dev/null +++ b/example/partition/struct/2d/stage2/01b/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocksv3.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01b/Partition.h b/example/partition/struct/2d/stage2/01b/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage2/01b/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage2/01b/README.txt b/example/partition/struct/2d/stage2/01b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage2/01b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage2/01b/SplitZone.cpp b/example/partition/struct/2d/stage2/01b/SplitZone.cpp new file mode 100644 index 00000000..e7ffa1b3 --- /dev/null +++ b/example/partition/struct/2d/stage2/01b/SplitZone.cpp @@ -0,0 +1,1065 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage2/01b/SplitZone.h b/example/partition/struct/2d/stage2/01b/SplitZone.h new file mode 100644 index 00000000..6ba99614 --- /dev/null +++ b/example/partition/struct/2d/stage2/01b/SplitZone.h @@ -0,0 +1,194 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage2/01b/heat2d2blocksv3.cgns b/example/partition/struct/2d/stage2/01b/heat2d2blocksv3.cgns new file mode 100644 index 00000000..d5c1096e Binary files /dev/null and b/example/partition/struct/2d/stage2/01b/heat2d2blocksv3.cgns differ diff --git a/example/partition/struct/2d/stage2/01b/main.cpp b/example/partition/struct/2d/stage2/01b/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage2/01b/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage2/01c/CMakeLists.txt b/example/partition/struct/2d/stage2/01c/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage2/01c/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage2/01c/CgnsGrid.cpp b/example/partition/struct/2d/stage2/01c/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage2/01c/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01c/CgnsGrid.h b/example/partition/struct/2d/stage2/01c/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage2/01c/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01c/Partition.cpp b/example/partition/struct/2d/stage2/01c/Partition.cpp new file mode 100644 index 00000000..f8d26e33 --- /dev/null +++ b/example/partition/struct/2d/stage2/01c/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocksv4.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01c/Partition.h b/example/partition/struct/2d/stage2/01c/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage2/01c/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage2/01c/README.txt b/example/partition/struct/2d/stage2/01c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage2/01c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage2/01c/SplitZone.cpp b/example/partition/struct/2d/stage2/01c/SplitZone.cpp new file mode 100644 index 00000000..e7ffa1b3 --- /dev/null +++ b/example/partition/struct/2d/stage2/01c/SplitZone.cpp @@ -0,0 +1,1065 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage2/01c/SplitZone.h b/example/partition/struct/2d/stage2/01c/SplitZone.h new file mode 100644 index 00000000..6ba99614 --- /dev/null +++ b/example/partition/struct/2d/stage2/01c/SplitZone.h @@ -0,0 +1,194 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage2/01c/heat2d2blocksv4.cgns b/example/partition/struct/2d/stage2/01c/heat2d2blocksv4.cgns new file mode 100644 index 00000000..199a53cf Binary files /dev/null and b/example/partition/struct/2d/stage2/01c/heat2d2blocksv4.cgns differ diff --git a/example/partition/struct/2d/stage2/01c/heat2dpart.cgns b/example/partition/struct/2d/stage2/01c/heat2dpart.cgns new file mode 100644 index 00000000..6c5ee464 Binary files /dev/null and b/example/partition/struct/2d/stage2/01c/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage2/01c/main.cpp b/example/partition/struct/2d/stage2/01c/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage2/01c/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage2/01d/CMakeLists.txt b/example/partition/struct/2d/stage2/01d/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage2/01d/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage2/01d/CgnsGrid.cpp b/example/partition/struct/2d/stage2/01d/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage2/01d/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01d/CgnsGrid.h b/example/partition/struct/2d/stage2/01d/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage2/01d/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01d/Partition.cpp b/example/partition/struct/2d/stage2/01d/Partition.cpp new file mode 100644 index 00000000..6b0e6ccb --- /dev/null +++ b/example/partition/struct/2d/stage2/01d/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocksv5.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01d/Partition.h b/example/partition/struct/2d/stage2/01d/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage2/01d/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage2/01d/README.txt b/example/partition/struct/2d/stage2/01d/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage2/01d/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage2/01d/SplitZone.cpp b/example/partition/struct/2d/stage2/01d/SplitZone.cpp new file mode 100644 index 00000000..e7ffa1b3 --- /dev/null +++ b/example/partition/struct/2d/stage2/01d/SplitZone.cpp @@ -0,0 +1,1065 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage2/01d/SplitZone.h b/example/partition/struct/2d/stage2/01d/SplitZone.h new file mode 100644 index 00000000..6ba99614 --- /dev/null +++ b/example/partition/struct/2d/stage2/01d/SplitZone.h @@ -0,0 +1,194 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage2/01d/heat2d2blocksv5.cgns b/example/partition/struct/2d/stage2/01d/heat2d2blocksv5.cgns new file mode 100644 index 00000000..4295b7b0 Binary files /dev/null and b/example/partition/struct/2d/stage2/01d/heat2d2blocksv5.cgns differ diff --git a/example/partition/struct/2d/stage2/01d/heat2dpart.cgns b/example/partition/struct/2d/stage2/01d/heat2dpart.cgns new file mode 100644 index 00000000..284f2e2c Binary files /dev/null and b/example/partition/struct/2d/stage2/01d/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage2/01d/main.cpp b/example/partition/struct/2d/stage2/01d/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage2/01d/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage2/01e/CMakeLists.txt b/example/partition/struct/2d/stage2/01e/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage2/01e/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage2/01e/CgnsGrid.cpp b/example/partition/struct/2d/stage2/01e/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage2/01e/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01e/CgnsGrid.h b/example/partition/struct/2d/stage2/01e/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage2/01e/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01e/Partition.cpp b/example/partition/struct/2d/stage2/01e/Partition.cpp new file mode 100644 index 00000000..ab857e0c --- /dev/null +++ b/example/partition/struct/2d/stage2/01e/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d2blocksv6.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 4; + this->nProc = 16; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage2/01e/Partition.h b/example/partition/struct/2d/stage2/01e/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage2/01e/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage2/01e/README.txt b/example/partition/struct/2d/stage2/01e/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage2/01e/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage2/01e/SplitZone.cpp b/example/partition/struct/2d/stage2/01e/SplitZone.cpp new file mode 100644 index 00000000..e7ffa1b3 --- /dev/null +++ b/example/partition/struct/2d/stage2/01e/SplitZone.cpp @@ -0,0 +1,1065 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage2/01e/SplitZone.h b/example/partition/struct/2d/stage2/01e/SplitZone.h new file mode 100644 index 00000000..6ba99614 --- /dev/null +++ b/example/partition/struct/2d/stage2/01e/SplitZone.h @@ -0,0 +1,194 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage2/01e/heat2d2blocksv6.cgns b/example/partition/struct/2d/stage2/01e/heat2d2blocksv6.cgns new file mode 100644 index 00000000..3c06915e Binary files /dev/null and b/example/partition/struct/2d/stage2/01e/heat2d2blocksv6.cgns differ diff --git a/example/partition/struct/2d/stage2/01e/heat2dpart.cgns b/example/partition/struct/2d/stage2/01e/heat2dpart.cgns new file mode 100644 index 00000000..f7de0491 Binary files /dev/null and b/example/partition/struct/2d/stage2/01e/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage2/01e/main.cpp b/example/partition/struct/2d/stage2/01e/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage2/01e/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage3/01/CMakeLists.txt b/example/partition/struct/2d/stage3/01/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage3/01/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage3/01/CgnsGrid.cpp b/example/partition/struct/2d/stage3/01/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage3/01/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01/CgnsGrid.h b/example/partition/struct/2d/stage3/01/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage3/01/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01/Partition.cpp b/example/partition/struct/2d/stage3/01/Partition.cpp new file mode 100644 index 00000000..5deeaf02 --- /dev/null +++ b/example/partition/struct/2d/stage3/01/Partition.cpp @@ -0,0 +1,618 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d1blockv1.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + this->nProc = 2; + //this->nProc = 16; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01/Partition.h b/example/partition/struct/2d/stage3/01/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage3/01/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage3/01/README.txt b/example/partition/struct/2d/stage3/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage3/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage3/01/SplitZone.cpp b/example/partition/struct/2d/stage3/01/SplitZone.cpp new file mode 100644 index 00000000..e7ffa1b3 --- /dev/null +++ b/example/partition/struct/2d/stage3/01/SplitZone.cpp @@ -0,0 +1,1065 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage3/01/SplitZone.h b/example/partition/struct/2d/stage3/01/SplitZone.h new file mode 100644 index 00000000..6ba99614 --- /dev/null +++ b/example/partition/struct/2d/stage3/01/SplitZone.h @@ -0,0 +1,194 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage3/01/heat2d1blockv1.cgns b/example/partition/struct/2d/stage3/01/heat2d1blockv1.cgns new file mode 100644 index 00000000..4aa7832a Binary files /dev/null and b/example/partition/struct/2d/stage3/01/heat2d1blockv1.cgns differ diff --git a/example/partition/struct/2d/stage3/01/heat2dpart.cgns b/example/partition/struct/2d/stage3/01/heat2dpart.cgns new file mode 100644 index 00000000..b5a8e3aa Binary files /dev/null and b/example/partition/struct/2d/stage3/01/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage3/01/main.cpp b/example/partition/struct/2d/stage3/01/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage3/01/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage3/01a/CMakeLists.txt b/example/partition/struct/2d/stage3/01a/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage3/01a/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage3/01a/CgnsGrid.cpp b/example/partition/struct/2d/stage3/01a/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage3/01a/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01a/CgnsGrid.h b/example/partition/struct/2d/stage3/01a/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage3/01a/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01a/Partition.cpp b/example/partition/struct/2d/stage3/01a/Partition.cpp new file mode 100644 index 00000000..d1c039a3 --- /dev/null +++ b/example/partition/struct/2d/stage3/01a/Partition.cpp @@ -0,0 +1,620 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d1blockv1.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + this->nProc = 3; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + //std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + std::vector< InterfaceSplitBc * > bc1to1List; + splitZone->GetLeafInterfaceBc( bc1to1List ); + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01a/Partition.h b/example/partition/struct/2d/stage3/01a/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage3/01a/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage3/01a/README.txt b/example/partition/struct/2d/stage3/01a/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage3/01a/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage3/01a/SplitZone.cpp b/example/partition/struct/2d/stage3/01a/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/2d/stage3/01a/SplitZone.cpp @@ -0,0 +1,1091 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nChild = this->child.size(); + if ( nChild == 0 ) + { + leafInterfaceBcList.push_back( this ); + } + else + { + for ( int iChild = 0; iChild < nChild; ++ iChild ) + { + InterfaceSplitBc * interfaceSplitBc = this->child[ iChild ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } + } +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + +void SplitZone::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nInterfaceBcs = this->interfaceSplitBcList.size(); + for ( int i = 0; i < nInterfaceBcs; ++ i ) + { + InterfaceSplitBc * interfaceSplitBc = this->interfaceSplitBcList[ i ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage3/01a/SplitZone.h b/example/partition/struct/2d/stage3/01a/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/2d/stage3/01a/SplitZone.h @@ -0,0 +1,196 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage3/01a/heat2d1blockv1.cgns b/example/partition/struct/2d/stage3/01a/heat2d1blockv1.cgns new file mode 100644 index 00000000..4aa7832a Binary files /dev/null and b/example/partition/struct/2d/stage3/01a/heat2d1blockv1.cgns differ diff --git a/example/partition/struct/2d/stage3/01a/heat2dpart.cgns b/example/partition/struct/2d/stage3/01a/heat2dpart.cgns new file mode 100644 index 00000000..8e4fd883 Binary files /dev/null and b/example/partition/struct/2d/stage3/01a/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage3/01a/main.cpp b/example/partition/struct/2d/stage3/01a/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage3/01a/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage3/01b/CMakeLists.txt b/example/partition/struct/2d/stage3/01b/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage3/01b/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage3/01b/CgnsGrid.cpp b/example/partition/struct/2d/stage3/01b/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage3/01b/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01b/CgnsGrid.h b/example/partition/struct/2d/stage3/01b/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage3/01b/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01b/Partition.cpp b/example/partition/struct/2d/stage3/01b/Partition.cpp new file mode 100644 index 00000000..f509f1d1 --- /dev/null +++ b/example/partition/struct/2d/stage3/01b/Partition.cpp @@ -0,0 +1,621 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d1blockv1.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + //this->nProc = 3; + this->nProc = 4; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + //std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + std::vector< InterfaceSplitBc * > bc1to1List; + splitZone->GetLeafInterfaceBc( bc1to1List ); + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01b/Partition.h b/example/partition/struct/2d/stage3/01b/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage3/01b/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage3/01b/README.txt b/example/partition/struct/2d/stage3/01b/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage3/01b/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage3/01b/SplitZone.cpp b/example/partition/struct/2d/stage3/01b/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/2d/stage3/01b/SplitZone.cpp @@ -0,0 +1,1091 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nChild = this->child.size(); + if ( nChild == 0 ) + { + leafInterfaceBcList.push_back( this ); + } + else + { + for ( int iChild = 0; iChild < nChild; ++ iChild ) + { + InterfaceSplitBc * interfaceSplitBc = this->child[ iChild ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } + } +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + +void SplitZone::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nInterfaceBcs = this->interfaceSplitBcList.size(); + for ( int i = 0; i < nInterfaceBcs; ++ i ) + { + InterfaceSplitBc * interfaceSplitBc = this->interfaceSplitBcList[ i ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage3/01b/SplitZone.h b/example/partition/struct/2d/stage3/01b/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/2d/stage3/01b/SplitZone.h @@ -0,0 +1,196 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage3/01b/heat2d1blockv1.cgns b/example/partition/struct/2d/stage3/01b/heat2d1blockv1.cgns new file mode 100644 index 00000000..4aa7832a Binary files /dev/null and b/example/partition/struct/2d/stage3/01b/heat2d1blockv1.cgns differ diff --git a/example/partition/struct/2d/stage3/01b/heat2dpart.cgns b/example/partition/struct/2d/stage3/01b/heat2dpart.cgns new file mode 100644 index 00000000..e583dfce Binary files /dev/null and b/example/partition/struct/2d/stage3/01b/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage3/01b/main.cpp b/example/partition/struct/2d/stage3/01b/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage3/01b/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage3/01c/CMakeLists.txt b/example/partition/struct/2d/stage3/01c/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage3/01c/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage3/01c/CgnsGrid.cpp b/example/partition/struct/2d/stage3/01c/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage3/01c/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01c/CgnsGrid.h b/example/partition/struct/2d/stage3/01c/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage3/01c/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01c/Partition.cpp b/example/partition/struct/2d/stage3/01c/Partition.cpp new file mode 100644 index 00000000..060c5c0b --- /dev/null +++ b/example/partition/struct/2d/stage3/01c/Partition.cpp @@ -0,0 +1,621 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d1blockv2.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + //this->nProc = 3; + this->nProc = 8; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + //std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + std::vector< InterfaceSplitBc * > bc1to1List; + splitZone->GetLeafInterfaceBc( bc1to1List ); + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01c/Partition.h b/example/partition/struct/2d/stage3/01c/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage3/01c/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage3/01c/README.txt b/example/partition/struct/2d/stage3/01c/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage3/01c/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage3/01c/SplitZone.cpp b/example/partition/struct/2d/stage3/01c/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/2d/stage3/01c/SplitZone.cpp @@ -0,0 +1,1091 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nChild = this->child.size(); + if ( nChild == 0 ) + { + leafInterfaceBcList.push_back( this ); + } + else + { + for ( int iChild = 0; iChild < nChild; ++ iChild ) + { + InterfaceSplitBc * interfaceSplitBc = this->child[ iChild ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } + } +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + +void SplitZone::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nInterfaceBcs = this->interfaceSplitBcList.size(); + for ( int i = 0; i < nInterfaceBcs; ++ i ) + { + InterfaceSplitBc * interfaceSplitBc = this->interfaceSplitBcList[ i ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage3/01c/SplitZone.h b/example/partition/struct/2d/stage3/01c/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/2d/stage3/01c/SplitZone.h @@ -0,0 +1,196 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage3/01c/heat2d1blockv2.cgns b/example/partition/struct/2d/stage3/01c/heat2d1blockv2.cgns new file mode 100644 index 00000000..93a1b73e Binary files /dev/null and b/example/partition/struct/2d/stage3/01c/heat2d1blockv2.cgns differ diff --git a/example/partition/struct/2d/stage3/01c/main.cpp b/example/partition/struct/2d/stage3/01c/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage3/01c/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/example/partition/struct/2d/stage3/01d/CMakeLists.txt b/example/partition/struct/2d/stage3/01d/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/2d/stage3/01d/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.30) + +project( testprj ) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +find_package(Eigen3 CONFIG REQUIRED) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +#list ( APPEND PRJ_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR} ) +list ( APPEND PRJ_LIBRARIES Eigen3::Eigen ) +set ( CGNS_INCLUDE_DIRS $ENV{CGNS_INC} ) +set ( CGNS_LIBRARIES $ENV{CGNS_LIB_SHARED_NAME} ) + +if ( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" ) + set ( CGNS_ROOT "C:/dev/cgns/4.4.0" ) + set ( CGNS_LIBNAME "cgnsdll.lib" ) + + set ( CGNS_INCLUDE_DIRS "${CGNS_ROOT}/include" CACHE PATH "path to CGNS headers" ) + set ( CGNS_LIBRARIES "${CGNS_ROOT}/lib/${CGNS_LIBNAME}" CACHE PATH "path to CGNS library" ) +endif() + +list ( APPEND PRJ_LIBRARIES ${CGNS_LIBRARIES} ) +list ( APPEND PRJ_INCLUDE_DIRS ${CGNS_INCLUDE_DIRS} ) + +if ( WIN32 ) + list ( APPEND PRJ_COMPILE_DEFINITIONS USE_DLL ) +endif () + +message( STATUS "PRJ_INCLUDE_DIRS = ${PRJ_INCLUDE_DIRS}") + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +add_executable( ${PROJECT_NAME} +) + +set( PROJECT_SOURCES + main.cpp + Partition.h Partition.cpp + CgnsGrid.h CgnsGrid.cpp + SplitZone.h SplitZone.cpp +) + +message( STATUS "PROJECT_NAME = ${PROJECT_NAME}") +message( STATUS "PROJECT_SOURCES = ${PROJECT_SOURCES}") + +target_sources( ${PROJECT_NAME} + PRIVATE + ${PROJECT_SOURCES} +) + +target_include_directories ( ${PROJECT_NAME} + PRIVATE + ${PRJ_INCLUDE_DIRS} +) + +target_link_libraries( ${PROJECT_NAME} + PRIVATE + ${PRJ_LIBRARIES} +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) diff --git a/example/partition/struct/2d/stage3/01d/CgnsGrid.cpp b/example/partition/struct/2d/stage3/01d/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/2d/stage3/01d/CgnsGrid.cpp @@ -0,0 +1,349 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include + +Grid::Grid() +{ + ; +} + +Grid::~Grid() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } +} + +Coor::Coor() +{ + ; +} + +Coor::~Coor() +{ +} + +void Coor::DumpCoor() +{ + double * xd = reinterpret_cast(const_cast(coord.data())); + for ( int i = 0; i < this->nNodes; ++ i ) + { + //std::cout << coord[i] << " "; + std::cout << xd[ i ] << " "; + if( (i+1)%5 == 0 ) std::cout << "\n"; + } + std::cout << "\n"; +} + +Zone::Zone() +{ + ; +} + +Zone::~Zone() +{ + for ( int i = 0; i < bccos.size(); ++ i ) + { + delete bccos[ i ]; + } + + for ( int i = 0; i < coors.size(); ++ i ) + { + delete coors[ i ]; + } +} + +ZoneBc::ZoneBc() +{ + ; +} + +ZoneBc::~ZoneBc() +{ + delete this->patch; +} + + +ZoneBc1To1::ZoneBc1To1() +{ + ; +} + +ZoneBc1To1::~ZoneBc1To1() +{ +} + +ZoneBcPatch::ZoneBcPatch() +{ + ; +} + +ZoneBcPatch::~ZoneBcPatch() +{ +} + +std::vector Global::zones; +BaseZoneList Global::zone_names; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +Global::Global() +{ + ; +} + +Global::~Global() +{ +} + +void Global::FreeData() +{ + for ( int i = 0; i < zones.size(); ++ i ) + { + delete zones[ i ]; + } + zones.resize( 0 ); +} + + +void ReadCgnsGridBaseZone( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + BaseZone baseZone; + //baseZone.baseId = baseId; + baseZone.zone_name = zonename; + + Global::zone_names.AddBaseZone( baseZone ); + } + } + cg_close( fileId ); +} + +void ReadCgnsGrid( const std::string & filename ) +{ + int fileId = -1; + cg_open( filename.c_str(), CG_MODE_READ, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + int nbases = -1; + cg_nbases( fileId, &nbases ); + std::cout << "nbases = " << nbases << "\n"; + for ( int iBase = 0; iBase < nbases; ++ iBase ) + { + char basename[ 33 ]; + int baseId = iBase + 1; + int icelldim = -1; + int iphysdim = -1; + cg_base_read( fileId, baseId, basename, &icelldim, &iphysdim ); + std::cout << "icelldim = " << icelldim << " iphysdim = " << iphysdim << "\n"; + Global::cell_dim = icelldim; + Global::phys_dim = iphysdim; + int nzones = -1; + cg_nzones( fileId, baseId, &nzones ); + std::cout << "nzones = " << nzones << "\n"; + for ( int iZone = 0; iZone < nzones; ++ iZone ) + { + int zoneId = iZone + 1; + int index_dim = -1; + cg_index_dim( fileId, baseId, zoneId, &index_dim ); + std::cout << "index_dim = " << index_dim << "\n"; + + std::vector isize( index_dim * 3 ); + + Zone * zone = new Zone(); + Global::zones.push_back( zone ); + + char zonename[33]; + cg_zone_read( fileId, baseId, zoneId, zonename, isize.data() ); + + BaseZone baseZone; + baseZone.zone_name = zonename; + int gZoneId = Global::zone_names.FindBaseZone( baseZone ); + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } + + std::vector irmin( index_dim ); + std::vector irmax( index_dim ); + int nNodes = 1; + for ( int m = 0; m < index_dim; ++ m ) + { + /* lower range index */ + irmin[ m ] = 1; + /* upper range index of vertices */ + irmax[ m ] = isize[ m ]; + nNodes *= irmax[ m ]; + zone->nijk.push_back( isize[ m ] ); + } + std::cout << "nNodes = " << nNodes << "\n"; + + ZoneType_t zoneType; + cg_zone_type( fileId, baseId, zoneId, &zoneType ); + std::cout << "zoneType = " << zoneType << " ZoneTypeName = " << ZoneTypeName[zoneType] << "\n"; + int ncoords = -1; + cg_ncoords( fileId, baseId, zoneId, &ncoords ); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = icoord + 1; + DataType_t dataType; + char coordname[ 33 ]; + cg_coord_info( fileId, baseId, zoneId, coorId, &dataType, coordname ); + std::cout << "coordname = " << coordname << "\n"; + std::cout << "dataType = " << dataType << " DataTypeName = " << DataTypeName[dataType] << "\n"; + std::vector coord( nNodes * sizeof(double) ); + + Coor * coor = new Coor(); + zone->coors.push_back( coor ); + coor->coorname = coordname; + coor->nNodes = nNodes; + coor->coord.resize( nNodes * sizeof( double ) ); + + cg_coord_read( fileId, baseId, zoneId, coordname, dataType, irmin.data(), irmax.data(), coor->coord.data() ); + coor->DumpCoor(); + } + + int nbocos = -1; + cg_nbocos( fileId, baseId, zoneId, &nbocos ); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = iboco + 1; + GridLocation_t location; + cg_boco_gridlocation_read( fileId, baseId, zoneId, bccoId, &location ); + std::cout << "iboco = " << iboco << " location = " << location << " GridLocationName = " << GridLocationName[location] << "\n"; + + ZoneBc * zonebc = new ZoneBc(); + zone->bccos.push_back( zonebc ); + + char boconame[ 33 ]; + BCType_t bocotype; + PointSetType_t ptset_type; + cgsize_t npnts = 0; + std::vector normalIndex( index_dim, -1 ); + cgsize_t normalListSize = 0; + DataType_t normalDataType; + int ndataset = -1; + + cg_boco_info( fileId, baseId, zoneId, bccoId, boconame, &bocotype, &ptset_type, + &npnts, normalIndex.data(), &normalListSize, &normalDataType, &ndataset ); + zonebc->bcType = bocotype; + std::cout << "boconame = " << boconame << " bocotype = " << bocotype << " BCTypeName = " << BCTypeName[bocotype] << "\n"; + std::cout << "ptset_type = " << ptset_type << " PointSetTypeName = " << PointSetTypeName[ptset_type] << "\n"; + std::cout << "npnts = " << npnts << "\n"; + std::cout << "normalIndex = "; + for ( int i = 0; i < index_dim; ++ i ) + { + std::cout << normalIndex[ i ] << " "; + } + std::cout << "\n"; + std::cout << "normalListSize = " << normalListSize << "\n"; + std::cout << "normalDataType = " << normalDataType << " DataTypeName = " << DataTypeName[ normalDataType ] << "\n"; + std::cout << "ndataset = " << ndataset << "\n"; + + std::vector normalList( nNodes * iphysdim * sizeof( double ) ); + + std::vector pnts( npnts * index_dim ); + cg_boco_read( fileId, baseId, zoneId, bccoId, pnts.data(), normalList.data() ); + std::cout << "pnts = "; + for ( int i = 0; i < pnts.size(); ++ i ) + { + std::cout << pnts[ i ] << " "; + zonebc->pnts.push_back( pnts[ i ] ); + } + std::cout << "\n"; + + double * normal_d = reinterpret_cast( const_cast( normalList.data() ) ); + } + + int n1to1 = -1; + cg_n1to1( fileId, baseId, zoneId, &n1to1 ); + std::cout << "n1to1 = " << n1to1 << "\n"; + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int i1to1Id = i1to1 + 1; + + ZoneBc1To1 * zonebc_1to1 = new ZoneBc1To1(); + zone->bc1to1s.push_back( zonebc_1to1 ); + + char connectname[ 33 ]; + char donorname[ 33 ]; + cgsize_t npnts = 2; + std::vector range( npnts * index_dim ); + std::vector donor_range( npnts * index_dim ); + std::vector transform( index_dim ); + cg_1to1_read( fileId, baseId, zoneId, i1to1Id, connectname, donorname, range.data(), donor_range.data(), transform.data() ); + std::cout << "connectname = " << connectname << "\n"; + std::cout << "donorname = " << donorname << "\n"; + + std::cout << "range = \n"; + for ( int i = 0; i < range.size(); ++ i ) + { + std::cout << range[ i ] << " "; + } + std::cout << "\n"; + std::cout << "donor_range = \n"; + for ( int i = 0; i < donor_range.size(); ++ i ) + { + std::cout << donor_range[ i ] << " "; + } + std::cout << "\n"; + + BaseZone baseZone; + baseZone.zone_name = donorname; + int gDonorZoneId = Global::zone_names.FindBaseZone( baseZone ); + + zonebc_1to1->zoneid = gZoneId; + zonebc_1to1->transform = transform; + zonebc_1to1->donor_zoneid = gDonorZoneId; + + for ( int i = 0; i < range.size(); ++ i ) + { + zonebc_1to1->pnts.push_back( range[ i ] ); + zonebc_1to1->donor_pnts.push_back( donor_range[ i ] ); + } + + int kkk = 1; + } + } + int kkk = 1; + } + int kkk = 1; + cg_close( fileId ); +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01d/CgnsGrid.h b/example/partition/struct/2d/stage3/01d/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/2d/stage3/01d/CgnsGrid.h @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include + +class Grid; + +class Zone; + +class Grid +{ +public: + Grid(); + ~Grid(); +public: + int nZone; + std::vector x; + std::vector zones; +}; + + +class Coor +{ +public: + Coor(); + ~Coor(); +public: + std::string coorname; + int nNodes; + std::vector nijk; + std::vector coord; +public: + void DumpCoor(); +}; + +class ZoneBc; +class ZoneBc1To1; + +class Zone +{ +public: + Zone(); + ~Zone(); +public: + std::vector nijk; + std::vector bccos; + std::vector bc1to1s; + std::vector coors; +}; + +class ZoneBcPatch; +class ZoneBc +{ +public: + ZoneBc(); + ~ZoneBc(); +public: + int bcType; + int zoneid; + std::vector pnts; + ZoneBcPatch * patch = nullptr; +}; + +class ZoneBc1To1 +{ +public: + ZoneBc1To1(); + ~ZoneBc1To1(); +public: + int zoneid; + int donor_zoneid; + std::vector pnts; + std::vector donor_pnts; + std::vector transform; +}; + +class ZoneBcPatch +{ +public: + ZoneBcPatch(); + ~ZoneBcPatch(); +public: + int donor_zoneid; + std::vector transform; + std::vector donor_pnts; +}; + +class BaseZone +{ +public: + std::string zone_name; + bool operator < ( const BaseZone & rhs ) const + { + return this->zone_name < rhs.zone_name; + } +}; + +class BaseZoneList +{ +public: + std::map basezone_map; +public: + void AddBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter; + iter = basezone_map.find( baseZone ); + if ( iter == basezone_map.end() ) + { + int id = basezone_map.size(); + basezone_map.insert( std::make_pair( baseZone, id ) ); + } + } + + int FindBaseZone( const BaseZone & baseZone ) + { + std::map::iterator iter = basezone_map.find( baseZone ); + if ( iter != basezone_map.end() ) + { + return iter->second; + } + return -1; + } +}; + +class Global +{ +public: + Global(); + ~Global(); +public: + static int cell_dim; + static int phys_dim; + static std::vector zones; + static BaseZoneList zone_names; +public: + static void FreeData(); +}; + +void ReadCgnsGrid( const std::string & filename ); +void ReadCgnsGridBaseZone( const std::string & filename ); \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01d/Partition.cpp b/example/partition/struct/2d/stage3/01d/Partition.cpp new file mode 100644 index 00000000..18f11ac2 --- /dev/null +++ b/example/partition/struct/2d/stage3/01d/Partition.cpp @@ -0,0 +1,621 @@ +#include "Partition.h" +#include "CgnsGrid.h" +#include "SplitZone.h" +#include "cgnslib.h" +#include + +bool CmpSplitZone::operator() ( SplitZone * a, SplitZone * b ) const +{ + return a->zoneIndex < b->zoneIndex; +}; + + +double CalSumOfProcSpeed( std::vector & procSpeed ); +double CalSumOfProcSpeed( std::vector & procSpeed ) +{ + int nProc = procSpeed.size(); + double sumOfProcSpeed = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + sumOfProcSpeed += procSpeed[ iProc ]; + } + return sumOfProcSpeed; +} + +Partition::Partition() +{ + this->inputName = "../heat2d1blockv2.cgns"; + this->outName = "../heat2dpart.cgns"; +} + +Partition::~Partition() +{ + ; +} + +int Partition::GetMinValueIndex( double * data, int numberOfData ) +{ + double minValue = data[ 0 ]; + int minimumValueIndex = 0; + + for ( int iData = 1; iData < numberOfData; ++ iData ) + { + if ( minValue > data[ iData ] ) + { + minValue = data[ iData ]; + minimumValueIndex = iData; + } + } + return minimumValueIndex; +} + +int Partition::GetMinLoadProc() +{ + return this->GetMinValueIndex( this->timeProc.data(), this->nProc ); +} + +SplitZone * Partition::GetLargestZone() +{ + SplitZone * largestZone = 0; + + double nMaxCell = 0.0; + + for ( std::set< SplitZone * >::iterator iter = unsignedZoneGroup.begin(); iter != unsignedZoneGroup.end(); ++ iter ) + { + double nSize = ( * iter )->GetNCell(); + if ( nMaxCell < nSize ) + { + nMaxCell = nSize; + largestZone = * iter; + } + } + + return largestZone; +} + +void Partition::Solve() +{ + std::cout << "Partition::Split()\n"; + //this->nProc = 2; + //this->nProc = 3; + this->nProc = 16; + this->ReadGrid(); + this->Split(); + this->DumpPartitionedGridFile(); + this->FreeAllZones(); +} + +void Partition::ReadGrid() +{ + ReadCgnsGridBaseZone( this->inputName ); + ReadCgnsGrid( this->inputName ); + + this->nOriZone = ::Global::zones.size(); + Dim::dim = Global::cell_dim; + + std::cout << "numberOfBlocks = " << nOriZone << "\n"; + + this->refZone.resize( nOriZone ); + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = new SplitZone(); + refZone[ iZone ] = splitZone; + + splitZone->SetZoneIndex( iZone ); + splitZone->SetProcId( 0 ); + splitZone->SetParentAndChild( 0 ); + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + Zone * zone = ::Global::zones[ iZone ]; + + splitZone->dimInfo.dimList = zone->nijk; + + int nbccos = zone->bccos.size(); + std::cout << "nbccos = " << nbccos << "\n"; + + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zoneBc = zone->bccos[ ibcco ]; + + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + splitZone->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->bcType = zoneBc->bcType; + physicalSplitBc->SetRegion( zoneBc->pnts ); + physicalSplitBc->splitZone = splitZone; + } + + int nbc1to1s = zone->bc1to1s.size(); + + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + ZoneBc1To1 * zoneBc1To1 = zone->bc1to1s[ ibc1to1 ]; + + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + splitZone->interfaceSplitBcList.push_back( interfaceSplitBc ); + interfaceSplitBc->zone = splitZone; + interfaceSplitBc->region.SetRegion( zoneBc1To1->pnts ); + + interfaceSplitBc->transform = zoneBc1To1->transform; + interfaceSplitBc->CalcTransformMatrix(); + + interfaceSplitBc->donor_zone = refZone[ zoneBc1To1->donor_zoneid ]; + interfaceSplitBc->donor_region.SetRegion( zoneBc1To1->donor_pnts ); + } + } + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + SplitZone * splitZone = refZone[ iZone ]; + + int nbc1to1s = splitZone->interfaceSplitBcList.size(); + for ( int ibc1to1 = 0; ibc1to1 < nbc1to1s; ++ ibc1to1 ) + { + InterfaceSplitBc * interfaceSplitBc = splitZone->interfaceSplitBcList[ ibc1to1 ]; + InterfaceInfo interfaceInfo; + interfaceSplitBc->donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + } +} + +void Partition::Split() +{ + this->InitSplit(); + this->BinarySplit(); + this->ModifyZoneIndex(); + int kkk = 1; +} + +void Partition::InitSplit() +{ + //nZone is the number of zones in the original grid + //nProc is not the number of blocks in the end, but the number of processes that need to be divided. + //This difference occurs because the structure grid can have many blocks per process. + + //this->nProc = nProc; + //this->nPhyBlocks = referenceBlock.size(); + //this->nZone = this->nPhyBlocks; + + //tj Computation time on processor j + //Nk Number of internal grid-cells for zone j + //aveFloatOp: Number of Real operations per gridcell + //Gj The set of blocks allocated to process j + //Pj Real operations per second for process j + + //The Greedy Load Balancing Algorithm + //1.Compute an "ideal" uniprocessor time, Tuni = sum ( Nk * aveFloatOp )/ sum( Pj ). + //2.Set the group of unassigned blocks, Gu, to contain all blocks. The number of blocks in Nu=M, where M is the total number of blocks in the mesh. + //3.Start all processors with a very small fictitious zone to get a start tj=delt aveFloatOp/Pj, where delt<<1 is the size of the very small fictious zone. + //This is used to find the fastest processor in a heterogeneous system, tj could otherwise be set to 0 in the homogeneous case. + this->aveFloatOp = 1.0; + this->delta = 1.0e-5; + this->procSpeed.resize( nProc ); + this->timeProc.resize( nProc ); + + this->nTZone = this->nOriZone; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + procSpeed[ iProc ] = 1.0; + } + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + timeProc[ iProc ] = delta * aveFloatOp / procSpeed[ iProc ]; + } + + double sumProcSpeed = CalSumOfProcSpeed( procSpeed ); + + double sumProcOp = 0.0; + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + sumProcOp += refZone[ iZone ]->GetNCell() * aveFloatOp; + } + + this->idealUniProcTime = sumProcOp / sumProcSpeed; + + this->eps = 0.05; + + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + unsignedZoneGroup.insert( refZone[ iZone ] ); + } + + //Init zoneStorage + for ( int iZone = 0; iZone < nOriZone; ++ iZone ) + { + zoneStorage.insert( refZone[ iZone ] ); + } + + //Assign procSplitZone to each process + procSplitZone.resize( nProc ); + + this->minNumberCell = 1; + for ( int m = 0; m < Dim::dim; ++ m ) + { + this->minNumberCell *= 1; + } + + int kkk = 1; + +} + +void Partition::FreeAllZones() +{ + int iCount = 0; + for ( std::set < SplitZone * >::iterator iter = zoneStorage.begin(); iter != zoneStorage.end(); ++ iter ) + { + //cout << "iCount = " << iCount << "\n"; + ++ iCount; + delete * iter; + } +} + +int Partition::GetNZones( int iProc ) +{ + return this->procSplitZone[ iProc ].size(); +} + +SplitZone * Partition::GetSplitZone( int iProc, int zoneId ) +{ + return this->procSplitZone[ iProc ][ zoneId ]; +} + +void Partition::AddZoneToUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.insert( zone ); +} + +void Partition::RemoveZoneFromUnsignedGroup( SplitZone * zone ) +{ + this->unsignedZoneGroup.erase( zone ); +} + +void Partition::AddZoneToProcess( int iProc, SplitZone * zone ) +{ + this->procSplitZone[ iProc ].push_back( zone ); +} + +void Partition::AddNewZone( SplitZone * zone ) +{ + zone->SetZoneIndex( nTZone ++ ); + + this->AddZoneToUnsignedGroup( zone ); + + this->zoneStorage.insert( zone ); +} + +SplitZone * Partition::Split( SplitZone * zone, double nCell ) +{ + SplitZone * zoneL = new SplitZone(); + zoneL->SetParentAndChild( zone ); + + SplitZone * zoneR = new SplitZone(); + zoneR->SetParentAndChild( zone ); + + //Remove the original block from the UnsignedGroup + this->RemoveZoneFromUnsignedGroup( zone ); + + this->AddNewZone( zoneL ); + this->AddNewZone( zoneR ); + + zone->Split( zoneL, zoneR, nCell ); + + return zoneL; +} + +void Partition::BinarySplit() +{ + while ( ! unsignedZoneGroup.empty() ) + { + std::cout << "number of unsigned zone = " << unsignedZoneGroup.size() << "\n"; + int iProc = this->GetMinLoadProc(); + + //Get the block with the largest number of grids and its size + SplitZone * largestZone = this->GetLargestZone(); + + double nMaxCell = largestZone->GetNCell(); + + double aveFloatOp = this->aveFloatOp; + double tau = timeProc[ iProc ] + nMaxCell * aveFloatOp / procSpeed[ iProc ]; + + //It seems that EPS is still necessary + //The idea here is as follows. For the candidate blocks which can be divided into blocks, + //if the difference between the target blocks and the candidate blocks is too wide, + //the binarySplit method is adopted. The binarySplit blocks do not directly join the process, + //but enter the next round of screening. + + if ( tau > idealUniProcTime * ( 1.0 + eps ) ) + { + double nRest = ( tau - idealUniProcTime ) * procSpeed[ iProc ] / aveFloatOp; + + double nTarget = nMaxCell - nRest; + if ( nRest > this->minNumberCell && nTarget > this->minNumberCell ) + { + //It is necessary to divide blocks only when a certain number of points are satisfied. + double nHalf = nMaxCell / 2.0; + nMaxCell = nTarget; + double ratio = nMaxCell / nRest; + double oRatio = 1.0 / ratio; + + if ( std::max( ratio, oRatio ) < 3.0 ) + { + int kkk = 1; + largestZone = this->Split( largestZone, nMaxCell ); + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + else + { + this->Split( largestZone, nHalf ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } + else + { + //If the block is of the right size, join the process directly, and there is no need to split it. + timeProc[ iProc ] += nMaxCell * aveFloatOp / procSpeed[ iProc ]; + this->RemoveZoneFromUnsignedGroup( largestZone ); + this->AddZoneToProcess( iProc, largestZone ); + } + } +} + +void Partition::ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ) +{ + SplitZone * rootSplitZone = splitZone->GetRootZone(); + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + coord.resize( nNodes * sizeof(double) ); + + int index_dim = splitZone->dimInfo.dimList.size(); + Coor * coor = zone->coors[ icoord ]; + + double * xlocal = reinterpret_cast( const_cast( coord.data() ) ); + double * xglobal = reinterpret_cast( const_cast( coor->coord.data() ) ); + if ( index_dim == 1 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ i ]; + } + } + else if ( index_dim == 2 ) + { + int icount = 0; + int imin = splitZone->dimInfo.rmin[ 0 ] - 1; + int imax = splitZone->dimInfo.rmax[ 0 ]; + int jmin = splitZone->dimInfo.rmin[ 1 ] - 1; + int jmax = splitZone->dimInfo.rmax[ 1 ]; + int ni = rootSplitZone->dimInfo.dimList[ 0 ]; + int nj = rootSplitZone->dimInfo.dimList[ 1 ]; + for ( int j = jmin; j < jmax; ++ j ) + { + int jstride = j * ni; + for ( int i = imin; i < imax; ++ i ) + { + xlocal[ icount++ ] = xglobal[ jstride + i ]; + } + } + } +} + +void Partition::DumpBc( SplitZone * splitZone ) +{ +} + +void Partition::DumpPartitionedGridFile() +{ + std::cout << "\n"; + std::cout << "DumpPartitionedGridFile -------------------------------" << "\n"; + std::cout << "\n"; + int fileId = -1; + std::string filename = this->outName; + int ierr = cg_open( filename.c_str(), CG_MODE_WRITE, &fileId ); + std::cout << "fileId = " << fileId << "\n"; + + std::vector coordnames; + coordnames.push_back( "CoordinateX" ); + coordnames.push_back( "CoordinateY" ); + coordnames.push_back( "CoordinateZ" ); + + std::string basename = "Base"; + int baseId = -1; + int icelldim = Global::cell_dim; + int iphysdim = Global::phys_dim; + cg_base_write( fileId, basename.c_str(), icelldim, iphysdim, &baseId ); + + std::cout << "baseId = " << baseId << "\n"; + + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nZones = this->GetNZones( iProc ); + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + ZoneType_t zoneType = Structured; + + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + + int index_dim = splitZone->dimInfo.dimList.size(); + std::cout << "index_dim = " << index_dim << "\n"; + + splitZone->dimInfo.ComputeISize(); + + int isize_dim = index_dim * 3; + + std::vector isize( index_dim * 3, 0 ); + for ( int m = 0; m < isize_dim; ++ m ) + { + isize[ m ] = splitZone->dimInfo.isize[ m ]; + } + + int zoneId = -1; + + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + + std::string zonename = "Zone" + std::to_string( splitZone->newIndex ); + + cg_zone_write( fileId, baseId, zonename.c_str(), isize.data(), zoneType, &zoneId ); + + std::cout << "zoneId = " << zoneId << "\n"; + std::cout << "zonename = " << zonename << "\n"; + + splitZone->ComputeRminmax(); + + SplitZone * rootSplitZone = splitZone->GetRootZone(); + + Zone * zone = Global::zones[ rootSplitZone->zoneIndex ]; + + int ncoords = zone->coors.size(); + std::cout << "ncoords = " << ncoords << "\n"; + + for ( int icoord = 0; icoord < ncoords; ++ icoord ) + { + int coorId = -1; + DataType_t dataType = RealDouble; + std::string coordname = coordnames[ icoord ]; + Coor * coor = zone->coors[ icoord ]; + + int nNodes = splitZone->dimInfo.ComputeNumNodes(); + std::cout << "nNodes = " << nNodes << "\n"; + + std::vector coord; + ComputeCoor( splitZone, icoord, coord ); + + cg_coord_write( fileId, baseId, zoneId, dataType, coordname.c_str(), coord.data(), &coorId ); + + std::cout << "fileId = " << fileId << " baseId = " << baseId << " zoneId = " << zoneId << " coorId = " << coorId << "\n"; + } + + std::vector< PhysicalSplitBc * > &bccoList = splitZone->physicalSplitBcList; + + int nbocos = bccoList.size(); + std::cout << "nbocos = " << nbocos << "\n"; + for ( int iboco = 0; iboco < nbocos; ++ iboco ) + { + int bccoId = -1; + GridLocation_t location = Vertex; + + std::string boconame = "BC" + std::to_string( iboco + 1 ); + + PhysicalSplitBc * physicalSplitBc = bccoList[ iboco ]; + BCType_t bocotype = static_cast( physicalSplitBc->bcType ); + PointSetType_t ptset_type = PointRange; + cgsize_t npnts = 2; + std::vector pnts; + int nSize = physicalSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( physicalSplitBc->region.end[ i ] ); + } + + cg_boco_write( fileId, baseId, zoneId, boconame.c_str(), bocotype, ptset_type, npnts, pnts.data(), & bccoId ); + } + + //std::vector< InterfaceSplitBc * > & bc1to1List = splitZone->interfaceSplitBcList; + std::vector< InterfaceSplitBc * > bc1to1List; + splitZone->GetLeafInterfaceBc( bc1to1List ); + + int n1to1 = bc1to1List.size(); + std::cout << "n1to1 = " << n1to1 << "\n"; + + std::vector itranfrm( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + itranfrm[ m ] = m + 1; + } + for ( int i1to1 = 0; i1to1 < n1to1; ++ i1to1 ) + { + int index_conn = -1; + + InterfaceSplitBc * interfaceSplitBc = bc1to1List[ i1to1 ]; + + std::vector pnts; + std::vector pntsdonor; + int nSize = interfaceSplitBc->region.start.size(); + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.start[ i ] ); + } + for ( int i = 0; i < nSize; ++ i ) + { + pnts.push_back( interfaceSplitBc->region.end[ i ] ); + } + + int nPatchSize = interfaceSplitBc->donor_region.start.size(); + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.start[ i ] ); + } + for ( int i = 0; i < nPatchSize; ++ i ) + { + pntsdonor.push_back( interfaceSplitBc->donor_region.end[ i ] ); + } + int id = interfaceSplitBc->donor_zone->newIndex; + int oldZoneIndex = interfaceSplitBc->donor_zone->zoneIndex; + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + std::cout << "donor zone id = " << id << "\n"; + std::cout << "donor zone oldZoneIndex = " << oldZoneIndex << "\n"; + std::string donorname = "Zone" + std::to_string( id ); + std::string connectname = "Interface" + std::to_string( i1to1 ); + + std::cout << "donorname = " << donorname << "\n"; + std::cout << "connectname = " << connectname << "\n"; + + std::vector & itranfrm = interfaceSplitBc->transform; + + cg_1to1_write( fileId, baseId, zoneId, connectname.c_str(), donorname.c_str(), pnts.data(), pntsdonor.data(), itranfrm.data(), &index_conn ); + std::cout << "index_conn = " << index_conn << "\n"; + } + } + } + cg_close( fileId ); +} + +void Partition::ModifyZoneIndex() +{ + std::cout << "ModifyZoneIndex +++++++++++++++++++++++++ " << "\n"; + int globalZoneId = 0; + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::cout << "iProc = " << iProc << "\n"; + int nZones = this->GetNZones( iProc ); + std::cout << "nZones in Proc " << iProc << " = " << nZones << "\n"; + + for ( int iZone = 0; iZone < nZones; ++ iZone ) + { + SplitZone * splitZone = this->GetSplitZone( iProc, iZone ); + //splitZone->SetZoneIndex( globalZoneId++ ); + splitZone->newIndex = ( globalZoneId++ ); + std::cout << "splitZone->newIndex = " << splitZone->newIndex << "\n"; + std::cout << "splitZone->zoneIndex = " << splitZone->zoneIndex << "\n"; + } + } +} \ No newline at end of file diff --git a/example/partition/struct/2d/stage3/01d/Partition.h b/example/partition/struct/2d/stage3/01d/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/2d/stage3/01d/Partition.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +class SplitZone; + +struct CmpSplitZone +{ + bool operator() ( SplitZone * a, SplitZone * b ) const; +}; + +class Partition +{ +public: + Partition(); + ~Partition(); +protected: + std::set < SplitZone * > zoneStorage; + std::set < SplitZone *, CmpSplitZone > unsignedZoneGroup; + std::vector< SplitZone * > refZone; + std::vector< std::vector< SplitZone * > > procSplitZone; + std::vector procSpeed; + std::vector timeProc; + double aveFloatOp, delta; + double idealUniProcTime, eps; + int minNumberCell; + int nTZone; + int nOriZone; + int nProc; +public: + std::string inputName; + std::string outName; +public: + void Solve(); + void ReadGrid(); + void Split(); + void InitSplit(); + void BinarySplit(); + //void GreedySplit(); +public: + void AddNewZone( SplitZone * zone ); + void AddZoneToUnsignedGroup( SplitZone * zone ); + void RemoveZoneFromUnsignedGroup( SplitZone * zone ); + void AddZoneToProcess( int iProc, SplitZone * zone ); + void DumpPartitionedGridFile(); + void ModifyZoneIndex(); + void FreeAllZones(); + int GetNZones( int iProc ); + SplitZone * GetSplitZone( int iProc, int zoneId ); + void ComputeCoor( SplitZone * splitZone, int icoord, std::vector & coord ); + void DumpBc( SplitZone * splitZone ); +private: + int GetMinValueIndex( double * data, int numberOfData ); + int GetMinLoadProc(); + SplitZone * GetLargestZone(); + SplitZone * Split( SplitZone * zone, double nCell ); +}; + diff --git a/example/partition/struct/2d/stage3/01d/README.txt b/example/partition/struct/2d/stage3/01d/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/2d/stage3/01d/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/2d/stage3/01d/SplitZone.cpp b/example/partition/struct/2d/stage3/01d/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/2d/stage3/01d/SplitZone.cpp @@ -0,0 +1,1091 @@ +#include "SplitZone.h" +#include "cgnslib.h" +#include + +int Dim::dim = -1; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ) +{ + domainBox.start = zoneBox.start; + domainBox.end = zoneBox.end; + + int axis = iDomain / 2; + int direction = iDomain % 2; + + if ( direction == 0 ) + { + domainBox.end[ axis ] = domainBox.start[ axis ]; + } + else if ( direction == 1 ) + { + domainBox.start[ axis ] = domainBox.end[ axis ]; + } +} + +DimInfo::DimInfo() +{ + this->Init( 1 ); +} + +DimInfo::~DimInfo() +{ +} + +void DimInfo::Init( int dim ) +{ + this->dim = dim; + dimList.resize( this->dim, 1 ); + oriPoint.resize( this->dim, 0 ); +} + +DimInfo & DimInfo::operator = ( const DimInfo & rhs ) +{ + if ( this == & rhs ) return * this; + + this->dim = rhs.dim; + this->dimList = rhs.dimList; + this->oriPoint = rhs.oriPoint; + + return * this; +} + +int DimInfo::ComputeNumNodes() +{ + int nNodes = 1; + for ( int m = 0; m < this->dimList.size(); ++ m ) + { + nNodes *= this->dimList[ m ]; + } + return nNodes; +} + +void DimInfo::ComputeISize() +{ + int index_dim = this->dimList.size(); + this->isize.resize( index_dim * 3, 0 ); + for ( int m = 0; m < index_dim; ++ m ) + { + isize[ m ] = this->dimList[ m ]; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 1; + isize[ start + m ] = this->dimList[ m ] - 1; + } + + for ( int m = 0; m < index_dim; ++ m ) + { + int start = index_dim * 2; + isize[ start + m ] = 0; + } + + for ( int i = 0; i < isize.size(); ++ i ) + { + std::cout << "i = " << i << " isize = " << isize[i] << "\n"; + } +} + +void DimInfo::ComputeRminmax( std::vector & ref ) +{ + int index_dim = this->dimList.size(); + this->rmin.resize( index_dim ); + this->rmax.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + rmin[ m ] = ref[ m ] + 1; + rmax[ m ] = ref[ m ] + this->dimList[ m ]; + } + + std::cout << "rmin, rmax = \n"; + for ( int m = 0; m < index_dim; ++ m ) + { + std::cout << rmin[ m ] << " " << rmax[ m ] << "\n"; + } +} + +void DimInfo::Init( std::vector & dimList ) +{ + this->dim = dimList.size(); + this->dimList = dimList; + std::vector zero( dimList.size(), 0 ); + this->oriPoint = zero; +} + +void DimInfo::SetNewDimension( int axis, int newStart, int newWidth ) +{ + this->oriPoint[ axis ] = newStart; + this->dimList [ axis ] = newWidth; +} + +void DimInfo::GetZoneGlobalBox( RangeRegion &zoneBox ) +{ + int index_dim = this->dimList.size(); + zoneBox.start.resize( index_dim ); + zoneBox.end.resize( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + zoneBox.start[ m ] = this->oriPoint[ m ] + 1; + zoneBox.end[ m ] = this->oriPoint[ m ] + this->dimList[ m ]; + } +} + +void DimInfo::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + int index_dim = this->dimList.size(); + localBox.start.resize( index_dim ); + localBox.end.resize( index_dim ); + + for ( int m = 0; m < index_dim; ++ m ) + { + localBox.start[ m ] = globalBox.start[ m ] - this->oriPoint[ m ]; + localBox.end[ m ] = globalBox.end[ m ] - this->oriPoint[ m ]; + } +} + +RangeRegion::RangeRegion( int nSize ) +{ + this->Init( nSize ); +} + +RangeRegion::~RangeRegion() +{ +} + +void RangeRegion::Init( int nSize ) +{ + this->start.resize( nSize ); + this->end.resize( nSize ); +} + +RangeRegion & RangeRegion::operator = ( const RangeRegion & rhs ) +{ + if ( this == & rhs ) return * this; + + this->start = rhs.start; + this->end = rhs.end; + + return * this; +} + +bool RangeRegion::operator == ( const RangeRegion & rhs ) const +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( this->start[ m ] != rhs.start[ m ] || + this->end [ m ] != rhs.end [ m ] ) + { + return false; + } + } + return true; +} + +void RangeRegion::SetRegion( std::vector & pnts ) +{ + int index_dim = pnts.size() / 2; + for ( int m = 0; m < index_dim; ++ m ) + { + this->start[ m ] = pnts[ m ]; + this->end[ m ] = pnts[ index_dim + m ]; + } +} + +bool RangeRegion::InRegion( const RangeRegion & region ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + if ( ( this->start[ m ] < region.start[ m ] ) || ( this->end[ m ] > region.end[ m ] ) ) + { + return false; + } + } + return true; +} + +void RangeRegion::Normalize() +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + int minv = std::min( this->start[ m ], this->end[ m ] ); + int maxv = std::max( this->start[ m ], this->end[ m ] ); + this->start[ m ] = minv; + this->end[ m ] = maxv; + } +} + +void RangeRegion::Localize( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::ToGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] += oriPoint[ m ]; + this->end[ m ] += oriPoint[ m ]; + } +} + +void RangeRegion::ToLocal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + for ( int m = 0; m < nSize; ++ m ) + { + this->start[ m ] -= oriPoint[ m ]; + this->end[ m ] -= oriPoint[ m ]; + } +} + +void RangeRegion::PrintGlobal( std::vector & oriPoint ) +{ + int nSize = this->start.size(); + std::cout << "global start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "global end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ] + oriPoint[m]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +void RangeRegion::Print() +{ + int nSize = this->start.size(); + std::cout << "start:("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->start[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; + std::cout << "end :("; + for ( int m = 0; m < nSize; ++ m ) + { + std::cout << this->end[ m ]; + if ( m != nSize - 1 ) + { + std::cout << ","; + } + } + std::cout << ")\n"; +} + +bool CheckOverLapping( RangeRegion & overlapRegion ); + +bool ComputeOverlapRegion( RangeRegion & region1, RangeRegion & region2, RangeRegion & overlapRegion ) +{ + int index_dim = region1.start.size(); + overlapRegion.Init( index_dim ); + for ( int m = 0; m < index_dim; ++ m ) + { + int ijkmin1 = std::min( region1.start[ m ], region1.end[ m ] ); + int ijkmax1 = std::max( region1.start[ m ], region1.end[ m ] ); + int ijkmin2 = std::min( region2.start[ m ], region2.end[ m ] ); + int ijkmax2 = std::max( region2.start[ m ], region2.end[ m ] ); + if ( ( ijkmax1 < ijkmin2 ) || ( ijkmin1 > ijkmax2 ) ) + { + return false; + } + + int ijkmin = std::max( ijkmin1, ijkmin2 ); + int ijkmax = std::min( ijkmax1, ijkmax2 ); + + overlapRegion.start[ m ] = ijkmin; + overlapRegion.end [ m ] = ijkmax; + } + + return CheckOverLapping( overlapRegion ); +} + +bool CheckOverLapping( RangeRegion & overlapRegion ) +{ + int index_dim = overlapRegion.start.size(); + int iCount = 0; + for ( int m = 0; m < index_dim; ++ m ) + { + if ( overlapRegion.start[ m ] == overlapRegion.end[ m ] ) + { + ++ iCount; + } + } + + return ( iCount == 1 ); +} + +bool GetInterfaceRegion( RangeRegion & zoneBoxL, RangeRegion & zoneBoxR, RangeRegion & interfaceRegion ) +{ + int index_dim = zoneBoxL.start.size(); + int nDomains = 2 * index_dim; + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegionL; + GetDomainRegion( zoneBoxL, iDomain, domainRegionL ); + + for ( int jDomain = 0; jDomain < nDomains; ++ jDomain ) + { + RangeRegion domainRegionR; + GetDomainRegion( zoneBoxR, jDomain, domainRegionR ); + + if ( domainRegionL == domainRegionR ) + { + interfaceRegion = domainRegionL; + return true; + } + } + } + return false; +} + +void CreateInterfaceBc( SplitZone * zoneL, SplitZone * zoneR ) +{ + RangeRegion globalBoxL, globalBoxR, globalInterfaceRegion; + + zoneL->GetZoneGlobalBox( globalBoxL ); + zoneR->GetZoneGlobalBox( globalBoxR ); + + if ( ! GetInterfaceRegion( globalBoxL, globalBoxR, globalInterfaceRegion ) ) + { + return; + } + + RangeRegion localInterfaceRegionL, localInterfaceRegionR; + + zoneL->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionL ); + zoneR->GetZoneLocalBox( globalInterfaceRegion, localInterfaceRegionR ); + + int kkk = 1; + + InterfaceSplitBc * interfaceSplitBcL = new InterfaceSplitBc(); + zoneL->interfaceSplitBcList.push_back( interfaceSplitBcL ); + interfaceSplitBcL->zone = zoneL; + interfaceSplitBcL->region = localInterfaceRegionL; + + int nSize = localInterfaceRegionL.start.size(); + + std::vector transform; + + for ( int m = 0; m < nSize; ++ m ) + { + transform.push_back( m + 1 ); + } + + interfaceSplitBcL->transform = transform; + interfaceSplitBcL->CalcTransformMatrix(); + + interfaceSplitBcL->donor_zone = zoneR; + interfaceSplitBcL->donor_region = localInterfaceRegionR; + + InterfaceSplitBc * interfaceSplitBcR = new InterfaceSplitBc(); + zoneR->interfaceSplitBcList.push_back( interfaceSplitBcR ); + + interfaceSplitBcR->zone = zoneR; + interfaceSplitBcR->region = localInterfaceRegionR; + + interfaceSplitBcR->transform = transform; + interfaceSplitBcR->CalcTransformMatrix(); + + interfaceSplitBcR->donor_zone = zoneL; + interfaceSplitBcR->donor_region = localInterfaceRegionL; +} + + +PhysicalSplitBc::PhysicalSplitBc() +{ + this->region.Init( Dim::dim ); +} + +PhysicalSplitBc::~PhysicalSplitBc() +{ +} + +void PhysicalSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void PhysicalSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +void PhysicalSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = splitZone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +BasicSplitBc::BasicSplitBc() +{ + this->region.Init( Dim::dim ); +} + +BasicSplitBc::~BasicSplitBc() +{ + ; +} + +void BasicSplitBc::SetRegion( std::vector & pnts ) +{ + this->region.SetRegion( pnts ); +} + +void BasicSplitBc::SetRegion( RangeRegion & region ) +{ + this->region = region; +} + +int trans::M[ 3 ][ 3 ]; +std::vector trans::transform; + +int trans::sgn( int x ) +{ + if ( x >= 0 ) + { + return 1; + } + else + { + return -1; + } +} + +int trans::del( int x, int y ) +{ + if ( std::abs( x ) == std::abs( y ) ) + { + return 1; + } + return 0; +} + +void trans::ZeroMatrix() +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + trans::M[ i ][ j ] = 0; + } + } +} + +void trans::CalcTransformMatrix() +{ + int dim = trans::transform.size(); + if ( dim == 1 ) + { + int a = trans::transform[ 0 ]; + int sgna = trans::sgn( a ); + int a1 = trans::del( a, 1 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + } + else if ( dim == 2 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + } + else if ( dim == 3 ) + { + int a = trans::transform[ 0 ]; + int b = trans::transform[ 1 ]; + int c = trans::transform[ 2 ]; + int sgna = trans::sgn( a ); + int sgnb = trans::sgn( b ); + int sgnc = trans::sgn( c ); + int a1 = trans::del( a, 1 ); + int a2 = trans::del( a, 2 ); + int a3 = trans::del( a, 3 ); + int b1 = trans::del( b, 1 ); + int b2 = trans::del( b, 2 ); + int b3 = trans::del( b, 3 ); + int c1 = trans::del( c, 1 ); + int c2 = trans::del( c, 2 ); + int c3 = trans::del( c, 3 ); + trans::M[ 0 ][ 0 ] = sgna * a1; + trans::M[ 1 ][ 0 ] = sgna * a2; + trans::M[ 2 ][ 0 ] = sgna * a3; + trans::M[ 0 ][ 1 ] = sgnb * b1; + trans::M[ 1 ][ 1 ] = sgnb * b2; + trans::M[ 2 ][ 1 ] = sgnb * b3; + trans::M[ 0 ][ 2 ] = sgnc * c1; + trans::M[ 1 ][ 2 ] = sgnc * c2; + trans::M[ 2 ][ 2 ] = sgnc * c3; + } +} + +InterfaceInfo::InterfaceInfo() +{ + this->donor_region.Init( Dim::dim ); +} + +InterfaceInfo::~InterfaceInfo() +{ +} + +InterfaceSplitBc::InterfaceSplitBc() +{ + this->region.Init( Dim::dim ); + this->donor_region.Init( Dim::dim ); +} + +InterfaceSplitBc::~InterfaceSplitBc() +{ +} + +void InterfaceSplitBc::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nChild = this->child.size(); + if ( nChild == 0 ) + { + leafInterfaceBcList.push_back( this ); + } + else + { + for ( int iChild = 0; iChild < nChild; ++ iChild ) + { + InterfaceSplitBc * interfaceSplitBc = this->child[ iChild ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } + } +} + +void InterfaceSplitBc::CopyMatrix( InterfaceSplitBc * interfaceSplitBc ) +{ + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = interfaceSplitBc->Mt[ i ][ j ]; + } + } +} + +void InterfaceSplitBc::CalcTransformMatrix() +{ + trans::ZeroMatrix(); + trans::transform = this->transform; + trans::CalcTransformMatrix(); + + int dim = 3; + for ( int j = 0; j < dim; ++ j ) + { + for ( int i = 0; i < dim; ++ i ) + { + this->Mt[ i ][ j ] = trans::M[ i ][ j ]; + } + } + +} + +void InterfaceSplitBc::mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ) +{ + int dim = Dim::dim; + std::vector diff( dim ); + for ( int m = 0; m < dim; ++ m ) + { + diff[ m ] = index1[ m ] - begin1[ m ]; + } + + std::vector mul( dim ); + + Multiply( Mt, diff, mul ); + + for ( int m = 0; m < dim; ++ m ) + { + index2[ m ] = mul[ m ] + begin2[ m ]; + } +} + +void InterfaceSplitBc::Multiply( int Mt[][3], std::vector & a, std::vector & b ) +{ + int dim = Dim::dim; + for ( int i = 0; i < dim; ++ i ) + { + b[ i ] = 0; + for ( int j = 0; j < dim; ++ j ) + { + b[ i ] += Mt[ i ][ j ] * a[ j ]; + } + } +} + +void InterfaceSplitBc::ChangeRegionToLocalCoordinate() +{ + int index_dim = this->region.start.size(); + std::vector & oriPoint = this->zone->dimInfo.oriPoint; + for ( int m = 0; m < index_dim; ++ m ) + { + this->region.start[ m ] -= oriPoint[ m ]; + this->region.end[ m ] -= oriPoint[ m ]; + } +} + +void InterfaceSplitBc::CalcSubDonorRegion( RangeRegion &subRegion, RangeRegion &subDonorRegion ) +{ + std::vector begin1 = this->region.start; + std::vector end1 = this->region.end; + std::vector begin2 = this->donor_region.start; + std::vector end2 = this->donor_region.end; + + std::vector new_begin1 = subRegion.start; + std::vector new_end1 = subRegion.end; + + int dim = Dim::dim; + std::vector new_begin2( dim ); + std::vector new_end2( dim ); + + mapindex( begin1, begin2, new_begin1, new_begin2 ); + mapindex( begin1, begin2, new_end1, new_end2 ); + + subDonorRegion.start = new_begin2; + subDonorRegion.end = new_end2; +} + +SplitZone::SplitZone() +{ + this->parent = 0; + this->zoneIndex = 0; + this->iProc = 0; + dimInfo.Init( Dim::dim ); + int kk = 1; +} + +SplitZone::~SplitZone() +{ + ; +} + +void SplitZone::GetZoneGlobalBox( RangeRegion & zoneBox ) +{ + this->dimInfo.GetZoneGlobalBox( zoneBox ); +} + +void SplitZone::GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ) +{ + this->dimInfo.GetZoneLocalBox( globalBox, localBox ); +} + + +void SplitZone::ComputeRminmax() +{ + int index_dim = this->dimInfo.dimList.size(); + std::vector ref( index_dim, 0 ); + + SplitZone * rootSplitZone = 0; + this->GetRootInfo( rootSplitZone, ref ); + + this->dimInfo.ComputeRminmax( ref ); +} + +SplitZone * SplitZone::GetRootZone() +{ + SplitZone * root = this; + + while ( true ) + { + if ( root->parent ) + { + root = root->parent; + } + else + { + return root; + } + }; +} + +void SplitZone::GetRootInfo( SplitZone *& root, std::vector & ref ) +{ + for ( int i = 0; i < this->dimInfo.dimList.size(); ++ i ) + { + ref[ i ] += this->dimInfo.oriPoint[ i ]; + } + + if ( this->parent ) + { + this->parent->GetRootInfo( root, ref ); + } + else + { + root = this; + } +} + +void SplitZone::SetParentAndChild( SplitZone * parent ) +{ + this->parent = parent; + if ( parent ) + { + parent->child.push_back( this ); + } +} + +void SplitZone::GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ) +{ + int nInterfaceBcs = this->interfaceSplitBcList.size(); + for ( int i = 0; i < nInterfaceBcs; ++ i ) + { + InterfaceSplitBc * interfaceSplitBc = this->interfaceSplitBcList[ i ]; + interfaceSplitBc->GetLeafInterfaceBc( leafInterfaceBcList ); + } +} + +int SplitZone::GetNCell() +{ + int numberOfCells = 1; + for ( int i = 0; i < this->dimInfo.dim; ++ i ) + { + numberOfCells *= std::max( 1, ( this->dimInfo.dimList[ i ] - 1 ) ); + } + + return numberOfCells; +} + +void SplitZone::SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int leftStart = 0; + int leftWidth = iSplit - 0; + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, leftStart , leftWidth ); +} + +void SplitZone::SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ) +{ + int rightStart = iSplit - 1; + int rightWidth = dimList[ axisNeedSplit ] - ( iSplit - 1 ); + + this->dimInfo.Init( dimList ); + this->dimInfo.SetNewDimension( axisNeedSplit, rightStart, rightWidth ); +} + +void SplitZone::Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ) +{ + //Find the longest axis + int axisNeedSplit = this->FindAxisNeedSplit(); + int iSplit = this->FindSplitPosition( axisNeedSplit, nCell ); + + zoneL->SetLeftDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + zoneR->SetRightDimension( this->dimInfo.dimList, axisNeedSplit, iSplit ); + + zoneL->CreateBcFromParent(); + zoneR->CreateBcFromParent(); + + CreateInterfaceBc( zoneL, zoneR ); +} + +void SplitZone::CreateBcFromParent() +{ + this->CreatePhysicalBcFromParent(); + this->CreateInterfaceBcFromParent(); +} + +void SplitZone::CreatePhysicalBcFromParent() +{ + int nParentPhysicalBcs = this->parent->physicalSplitBcList.size(); + + for ( int iParentPhysicalBcs = 0; iParentPhysicalBcs < nParentPhysicalBcs; ++ iParentPhysicalBcs ) + { + PhysicalSplitBc * parentPhysicalSplitBc = this->parent->physicalSplitBcList[ iParentPhysicalBcs ]; + + this->CreatePhysicalBcFromParent( parentPhysicalSplitBc ); + } +} + +void SplitZone::CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentPhysicalSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreatePhysicalBc( overlapRegion, parentPhysicalSplitBc->bcType ); + + int kkk = 1; + } +} + +void SplitZone::CreateInterfaceBcFromParent() +{ + int nInterfaceSplitBcs = this->parent->interfaceSplitBcList.size(); + + for ( int iInterfaceSplitBcs = 0; iInterfaceSplitBcs < nInterfaceSplitBcs; ++ iInterfaceSplitBcs ) + { + InterfaceSplitBc * parentInterfaceSplitBc = this->parent->interfaceSplitBcList[ iInterfaceSplitBcs ]; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc ); + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ) +{ + int index_dim = this->dimInfo.dimList.size(); + int nDomains = 2 * index_dim; + RangeRegion zoneBoxRegion( index_dim ); + this->dimInfo.GetZoneGlobalBox( zoneBoxRegion ); + + for ( int iDomain = 0; iDomain < nDomains; ++ iDomain ) + { + RangeRegion domainRegion( index_dim ); + GetDomainRegion( zoneBoxRegion, iDomain, domainRegion ); + + RangeRegion overlapRegion; + bool overlap_flag = ComputeOverlapRegion( parentInterfaceSplitBc->region, domainRegion, overlapRegion ); + if ( ! overlap_flag ) continue; + + this->CreateInterfaceBcFromParent( parentInterfaceSplitBc, overlapRegion ); + + int kkk = 1; + } +} + +void SplitZone::FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ) +{ + RangeRegion donor_region = interfaceSplitBc->donor_region; + donor_region.Normalize(); + interfaceInfo.donor_zone = this; + for ( int iInterface = 0; iInterface < interfaceSplitBcList.size(); ++ iInterface ) + { + InterfaceSplitBc * candidateDonorBc = interfaceSplitBcList[ iInterface ]; + bool flag = donor_region.InRegion( candidateDonorBc->region ); + if ( flag ) + { + if ( donor_region == candidateDonorBc->region ) + { + interfaceInfo.donor_interface = candidateDonorBc; + return; + } + else + { + InterfaceSplitBc * donorBc = new InterfaceSplitBc(); + candidateDonorBc->child.push_back( donorBc ); + donorBc->region = donor_region; + donorBc->zone = candidateDonorBc->zone; + donorBc->donor_zone = interfaceSplitBc->zone; + donorBc->transform = candidateDonorBc->transform; + donorBc->CopyMatrix( candidateDonorBc ); + RangeRegion subDonorRegion( Dim::dim ); + candidateDonorBc->CalcSubDonorRegion( donorBc->region, subDonorRegion ); + std::vector & oriPoint = interfaceSplitBc->zone->dimInfo.oriPoint; + subDonorRegion.Localize( oriPoint ); + donorBc->donor_region = subDonorRegion; + donorBc->donor_bc = interfaceSplitBc; + interfaceInfo.donor_interface = donorBc; + return; + } + } + } + return; +} + +void SplitZone::GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ) +{ + std::cout << "subDonorRegion = \n"; + //subDonorRegion.Print(); + RangeRegion normalizedDonorRegion = subDonorRegion; + normalizedDonorRegion.Normalize(); + int nChild = this->child.size(); + for ( int ichild = 0; ichild < nChild; ++ ichild ) + { + std::cout << " iChild = " << ichild << " nChild = " << nChild << "\n"; + SplitZone * sub_zone = this->child[ ichild ]; + std::cout << " zoneIndex = " << sub_zone->zoneIndex << "\n"; + int nInters = sub_zone->interfaceSplitBcList.size(); + for ( int iInter = 0; iInter < nInters; ++ iInter ) + { + std::cout << " iInter = " << iInter << "\n"; + InterfaceSplitBc * interfaceSplitBc = sub_zone->interfaceSplitBcList[ iInter ]; + std::cout << "interfaceSplitBc local = \n"; + interfaceSplitBc->region.Print(); + std::cout << "interfaceSplitBc global = \n"; + interfaceSplitBc->region.PrintGlobal( sub_zone->dimInfo.oriPoint ); + RangeRegion g_region = interfaceSplitBc->region; + g_region.ToGlobal( sub_zone->dimInfo.oriPoint ); + if ( g_region == normalizedDonorRegion ) + { + RangeRegion donorRegion = subDonorRegion; + donorRegion.ToLocal( sub_zone->dimInfo.oriPoint ); + + interfaceInfo.donor_zone = sub_zone; + interfaceInfo.donor_interface = interfaceSplitBc; + interfaceInfo.donor_region = donorRegion; + return; + } + } + } +} + +void SplitZone::CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ) +{ + InterfaceSplitBc * interfaceSplitBc = new InterfaceSplitBc(); + this->interfaceSplitBcList.push_back( interfaceSplitBc ); + + interfaceSplitBc->region = overlapRegion; + interfaceSplitBc->zone = this; + interfaceSplitBc->transform = parentInterfaceSplitBc->transform; + interfaceSplitBc->CopyMatrix( parentInterfaceSplitBc ); + RangeRegion subDonorRegion( Dim::dim ); + parentInterfaceSplitBc->CalcSubDonorRegion( overlapRegion, subDonorRegion ); + interfaceSplitBc->ChangeRegionToLocalCoordinate(); + interfaceSplitBc->donor_region = subDonorRegion; + SplitZone * parent_donor_zone = parentInterfaceSplitBc->donor_zone; + std::cout << " parentInterfaceSplitBc->zone->zoneIndex " << parentInterfaceSplitBc->zone->zoneIndex << "\n"; + std::cout << " parentInterfaceSplitBc->donor_zone->zoneIndex " << parent_donor_zone->zoneIndex << "\n"; + if ( parent_donor_zone->child.size() > 0 ) + { + InterfaceInfo interfaceInfo; + parent_donor_zone->GetChildDonorRegion( subDonorRegion, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + interfaceSplitBc->donor_region = interfaceInfo.donor_region; + //compatibility + InterfaceSplitBc * donor_bc = interfaceSplitBc->donor_bc; + SplitZone * donor_zone = interfaceSplitBc->donor_zone; + if ( interfaceSplitBc->zone != donor_bc->donor_zone ) + { + if ( interfaceSplitBc->zone->parent == donor_bc->donor_zone ) + { + RangeRegion d_region = donor_bc->donor_region; + d_region.ToLocal( interfaceSplitBc->zone->dimInfo.oriPoint ); + donor_bc->donor_region = d_region; + } + donor_bc->donor_zone = interfaceSplitBc->zone; + + int kkk = 1; + } + int kkk = 1; + } + else + { + InterfaceInfo interfaceInfo; + parent_donor_zone->FindDonorInterface( interfaceSplitBc, interfaceInfo ); + interfaceSplitBc->donor_zone = interfaceInfo.donor_zone; + interfaceSplitBc->donor_bc = interfaceInfo.donor_interface; + } + + int kkk = 1; +} + +void SplitZone::CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ) +{ + PhysicalSplitBc * physicalSplitBc = new PhysicalSplitBc(); + this->physicalSplitBcList.push_back( physicalSplitBc ); + physicalSplitBc->SetRegion( overlapRegion ); + physicalSplitBc->bcType = bcType; + physicalSplitBc->splitZone = this; + physicalSplitBc->ChangeRegionToLocalCoordinate(); +} + +int SplitZone::FindAxisNeedSplit() +{ + //Find the longest axis + int axisNeedSplit = 0; + int maxN = this->dimInfo.dimList[ 0 ]; + + for ( int m = 1; m < this->dimInfo.dimList.size(); ++ m ) + { + if ( this->IsPoleBc( m ) ) + { + continue; + } + int Nm = this->dimInfo.dimList[ m ]; + if ( maxN < Nm ) + { + maxN = Nm; + axisNeedSplit = m; + } + } + + return axisNeedSplit; +} + +int SplitZone::GetCrossSection( int axis ) +{ + int nDim = this->dimInfo.dimList.size(); + int crossSection = 1; + int N = nDim - 1; + for ( int m = 0; m < N; ++ m ) + { + int mm = ( axis + 1 ) % nDim; + int nLineElements = std::max( 1, ( this->dimInfo.dimList[ mm ] - 1 ) ); + crossSection *= nLineElements; + } + return crossSection; +} + +int SplitZone::FindSplitPosition( int axisNeedSplit, double nCell ) +{ + int nDim = this->dimInfo.dimList.size(); + std::vector crossSections( nDim ); + for ( int m = 0; m < nDim; ++ m ) + { + crossSections[ m ] = this->GetCrossSection( m ); + } + + //guess the value + double dSplit = nCell / crossSections[ axisNeedSplit ]; + int iSplit = 1 + static_cast< int >( std::floor( dSplit + 0.5 ) ); + return iSplit; +} + + +bool SplitZone::IsPoleBc( int splitDirection ) +{ + return false; +} + diff --git a/example/partition/struct/2d/stage3/01d/SplitZone.h b/example/partition/struct/2d/stage3/01d/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/2d/stage3/01d/SplitZone.h @@ -0,0 +1,196 @@ +#pragma once +#include +#include +#include + +class Dim +{ +public: + static int dim; +}; + +class SplitZone; +class RangeRegion; + +void GetDomainRegion( RangeRegion & zoneBox, int iDomain, RangeRegion & domainBox ); + +class DimInfo +{ +public: + DimInfo(); + ~DimInfo(); +public: + int dim; + std::vector dimList; + std::vector oriPoint; + std::vector isize; + std::vector rmin; + std::vector rmax; +public: + int GetSize() const { return dim; } + DimInfo & operator = ( const DimInfo & rhs ); +public: + int ComputeNumNodes(); + void ComputeISize(); + void ComputeRminmax( std::vector & ref ); + void Init( int dim ); + void Init( std::vector & dimList ); + void SetNewDimension( int axis, int newStart, int newWidth ); + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); +}; + +class SplitZone; +class SplitBcPatch; + +class RangeRegion +{ +public: + RangeRegion( int nSize = 1 ); + ~RangeRegion(); +public: + std::vector start; + std::vector end; +public: + void Init( int nSize ); + RangeRegion & operator = ( const RangeRegion & rhs ); + bool operator == ( const RangeRegion & rhs ) const; + bool InRegion( const RangeRegion & region ); + void SetRegion( std::vector &pnts ); + void Normalize(); + void Localize( std::vector & oriPoint ); + void ToGlobal( std::vector & oriPoint ); + void ToLocal( std::vector & oriPoint ); + void PrintGlobal( std::vector & oriPoint ); + void Print(); +}; + +class PhysicalSplitBc +{ +public: + PhysicalSplitBc(); + ~PhysicalSplitBc(); +public: + int bcType; + RangeRegion region; +public: + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector &pnts ); + void SetRegion( RangeRegion ®ion ); + void ChangeRegionToLocalCoordinate(); +}; + +class BasicSplitBc +{ +public: + BasicSplitBc(); + ~BasicSplitBc(); +public: + RangeRegion region; + SplitZone * splitZone = nullptr; +public: + void SetRegion( std::vector & pnts ); + void SetRegion( RangeRegion & region ); +}; + +class trans +{ +public: + static int M[ 3 ][ 3 ]; + static std::vector transform; + static int sgn( int x ); + static int del( int x, int y ); + static void ZeroMatrix(); + static void CalcTransformMatrix(); +}; + +class InterfaceSplitBc; +class SplitZone; + +class InterfaceInfo +{ +public: + InterfaceInfo(); + ~InterfaceInfo(); +public: + InterfaceSplitBc * donor_interface = nullptr; + SplitZone * donor_zone = nullptr; + RangeRegion donor_region; +}; + +class InterfaceSplitBc +{ +public: + InterfaceSplitBc(); + ~InterfaceSplitBc(); +public: + std::vector transform; + int Mt[ 3 ][ 3 ]; + RangeRegion region; + SplitZone * zone = nullptr; + RangeRegion donor_region; + SplitZone * donor_zone = nullptr; + InterfaceSplitBc * donor_bc = nullptr; +public: + std::vector child; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + void CopyMatrix( InterfaceSplitBc * interfaceSplitBc ); + void CalcTransformMatrix(); + void CalcSubDonorRegion( RangeRegion & subRegion, RangeRegion & subDonorRegion ); + void mapindex( std::vector & begin1, std::vector & begin2, std::vector & index1, std::vector & index2 ); + void Multiply( int Mt[][ 3 ], std::vector & a, std::vector & b ); + void ChangeRegionToLocalCoordinate(); +}; + +class SplitZone +{ +public: + SplitZone(); + ~SplitZone(); +public: + DimInfo dimInfo; + int zoneIndex, iProc; + int newIndex; +protected: + SplitZone * parent; + std::vector child; +public: + std::vector< PhysicalSplitBc * > physicalSplitBcList; + std::vector< InterfaceSplitBc * > interfaceSplitBcList; + void GetLeafInterfaceBc( std::vector< InterfaceSplitBc * > & leafInterfaceBcList ); +public: + int GetNCell(); + void ComputeRminmax(); + void GetRootInfo( SplitZone *& root, std::vector & ref ); + void SetZoneIndex( int zoneIndex ) { this->zoneIndex = zoneIndex; } + int GetZoneIndex() { return zoneIndex; } + void SetProcId( int iProc ) { this->iProc = iProc; } + void SetParent( SplitZone * parent ) { this->parent = parent; }; + void SetParentAndChild( SplitZone * parent ); + void FindDonorInterface( InterfaceSplitBc * interfaceSplitBc, InterfaceInfo & interfaceInfo ); + void GetChildDonorRegion( RangeRegion & subDonorRegion, InterfaceInfo & interfaceInfo ); +public: + void CreateBcFromParent(); + void CreatePhysicalBcFromParent(); + void CreatePhysicalBcFromParent( PhysicalSplitBc * parentPhysicalSplitBc ); + void CreatePhysicalBc( RangeRegion & overlapRegion, int bcType ); + void CreateInterfaceBcFromParent(); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc ); + void CreateInterfaceBcFromParent( InterfaceSplitBc * parentInterfaceSplitBc, RangeRegion & overlapRegion ); + + void GetZoneGlobalBox( RangeRegion & zoneBox ); + void GetZoneLocalBox( RangeRegion & globalBox, RangeRegion & localBox ); + SplitZone * GetRootZone(); +public: + void Split( SplitZone *& zoneL, SplitZone *& zoneR, double nCell ); + void SetLeftDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); + void SetRightDimension( std::vector & dimList, int axisNeedSplit, int iSplit ); +private: + int FindAxisNeedSplit(); + int FindSplitPosition( int axisNeedSplit, double nCell ); + bool IsPoleBc( int splitDirection ); + int GetCrossSection( int axis ); +}; + diff --git a/example/partition/struct/2d/stage3/01d/heat2d1blockv2.cgns b/example/partition/struct/2d/stage3/01d/heat2d1blockv2.cgns new file mode 100644 index 00000000..93a1b73e Binary files /dev/null and b/example/partition/struct/2d/stage3/01d/heat2d1blockv2.cgns differ diff --git a/example/partition/struct/2d/stage3/01d/heat2dpart.cgns b/example/partition/struct/2d/stage3/01d/heat2dpart.cgns new file mode 100644 index 00000000..0f631a2e Binary files /dev/null and b/example/partition/struct/2d/stage3/01d/heat2dpart.cgns differ diff --git a/example/partition/struct/2d/stage3/01d/main.cpp b/example/partition/struct/2d/stage3/01d/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/2d/stage3/01d/main.cpp @@ -0,0 +1,18 @@ +#include "cgnslib.h" +#include "CgnsGrid.h" +#include "Partition.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Partition * partition = new Partition(); + partition->Solve(); + delete partition; + + return 0; +} diff --git a/tools/CMakeLists.txt.user b/tools/CMakeLists.txt.user new file mode 100644 index 00000000..f1fc6354 --- /dev/null +++ b/tools/CMakeLists.txt.user @@ -0,0 +1,416 @@ + + + + + + EnvironmentId + {762d27bf-d7ff-4b95-a1d2-6c0057e05a84} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + 0 + false + true + false + 2 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + false + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 8 + true + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop (x86-windows-msvc2022-pe-64bit) + Desktop (x86-windows-msvc2022-pe-64bit) + {ec33f296-75bb-46b2-93fe-fc1d75202276} + 0 + 0 + 0 + + Debug + 2 + false + + -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_BUILD_TYPE:STRING=Debug +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + D:\github\OneFLOW\tools\build\Desktop_x86_windows_msvc2022_pe_64bit-Debug + + + + + all + + false + + true + Build + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + + clean + + false + + true + Build + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + CMakeProjectManager.CMakeBuildConfiguration + + + Release + 2 + false + + -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_BUILD_TYPE:STRING=Release +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + D:\github\OneFLOW\tools\build\Desktop_x86_windows_msvc2022_pe_64bit-Release + + + + + all + + false + + true + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + + clean + + false + + true + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + CMakeProjectManager.CMakeBuildConfiguration + + + RelWithDebInfo + 2 + false + + -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + D:\github\OneFLOW\tools\build\Desktop_x86_windows_msvc2022_pe_64bit-RelWithDebInfo + + + + + all + + false + + true + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + + clean + + false + + true + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release with Debug Information + CMakeProjectManager.CMakeBuildConfiguration + + + RelWithDebInfo + 2 + false + + -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + 0 + D:\github\OneFLOW\tools\build\Desktop_x86_windows_msvc2022_pe_64bit-Profile + + + + + all + + false + + true + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + + clean + + false + + true + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + CMakeProjectManager.CMakeBuildConfiguration + + + MinSizeRel + 2 + false + + -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_BUILD_TYPE:STRING=MinSizeRel +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + D:\github\OneFLOW\tools\build\Desktop_x86_windows_msvc2022_pe_64bit-MinSizeRel + + + + + all + + false + + true + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + + clean + + false + + true + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Minimum Size Release + CMakeProjectManager.CMakeBuildConfiguration + + 5 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph "dwarf,4096" -F 250 + ModernCFD + CMakeProjectManager.CMakeRunConfiguration.ModernCFD + ModernCFD + false + true + true + true + D:/github/OneFLOW/tools/build/Desktop_x86_windows_msvc2022_pe_64bit-Debug + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/tools/codes/cgnsview.cpp b/tools/codes/cgnsview.cpp index 38c07985..860e4434 100644 --- a/tools/codes/cgnsview.cpp +++ b/tools/codes/cgnsview.cpp @@ -245,6 +245,7 @@ void CgnsView::SetUpCgnsInfo() QString fileName = "D:/work/cgns_work/cgnsgrid_example/yf17_hdf5.cgns"; //QString fileName = "D:/work/cgns_work/ModernCGNS/codes/UserGuideCode/read_complex/complex_data.cgns"; //QString fileName = "D:/work/cgns_work/ModernCGNS/codes/UserGuideCode/cg_link_write/grid/links.cgns"; + //QString fileName = "D:/work/cgns_work/ModernCGNS/codes/UserGuideCode/cg_base_read/example.cgns"; ::ReadCgnsFile( fileName.toLatin1().data() );