diff --git a/example/1d-heat-equation/cn/cpp/singleblock/01/CMakeLists.txt b/example/1d-heat-equation/cn/cpp/singleblock/01/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/CgnsGrid.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/CgnsGrid.h b/example/1d-heat-equation/cn/cpp/singleblock/01/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/Field.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01/Field.cpp new file mode 100644 index 00000000..2f3a6e2e --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01/Field.cpp @@ -0,0 +1,320 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +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::CN( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + d[ ii ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +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/cn/cpp/singleblock/01/Field.h b/example/1d-heat-equation/cn/cpp/singleblock/01/Field.h new file mode 100644 index 00000000..a14588b8 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01/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 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 CN( 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/cn/cpp/singleblock/01/LogFile.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/LogFile.h b/example/1d-heat-equation/cn/cpp/singleblock/01/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/Parallel.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/Parallel.h b/example/1d-heat-equation/cn/cpp/singleblock/01/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/README.txt b/example/1d-heat-equation/cn/cpp/singleblock/01/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/Solver.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01/Solver.cpp new file mode 100644 index 00000000..563a40a3 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01/Solver.cpp @@ -0,0 +1,730 @@ +#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; + this->scheme = Scheme::CN; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + 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::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( 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/cn/cpp/singleblock/01/Solver.h b/example/1d-heat-equation/cn/cpp/singleblock/01/Solver.h new file mode 100644 index 00000000..9b925249 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01/Solver.h @@ -0,0 +1,65 @@ +#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, + CN, //Crank¨CNicolson + 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 CN(); + 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/cn/cpp/singleblock/01/ZoneState.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/ZoneState.h b/example/1d-heat-equation/cn/cpp/singleblock/01/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/global.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/global.h b/example/1d-heat-equation/cn/cpp/singleblock/01/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/heat1d1block.cgns b/example/1d-heat-equation/cn/cpp/singleblock/01/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/1d-heat-equation/cn/cpp/singleblock/01/heat1d1block.cgns differ diff --git a/example/1d-heat-equation/cn/cpp/singleblock/01/main.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/plot.py b/example/1d-heat-equation/cn/cpp/singleblock/01/plot.py new file mode 100644 index 00000000..dcc55c0b --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01/plotting2.jl b/example/1d-heat-equation/cn/cpp/singleblock/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/cn/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/cn/cpp/singleblock/01a/CMakeLists.txt b/example/1d-heat-equation/cn/cpp/singleblock/01a/CMakeLists.txt new file mode 100644 index 00000000..b7b5626e --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01a/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.31) + +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/cn/cpp/singleblock/01a/CgnsGrid.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01a/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/CgnsGrid.h b/example/1d-heat-equation/cn/cpp/singleblock/01a/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/Field.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01a/Field.cpp new file mode 100644 index 00000000..774b7f02 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01a/Field.cpp @@ -0,0 +1,325 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +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::CN( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + d[ ii ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +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/cn/cpp/singleblock/01a/Field.h b/example/1d-heat-equation/cn/cpp/singleblock/01a/Field.h new file mode 100644 index 00000000..a14588b8 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01a/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 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 CN( 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/cn/cpp/singleblock/01a/LogFile.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01a/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/LogFile.h b/example/1d-heat-equation/cn/cpp/singleblock/01a/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/Parallel.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01a/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/Parallel.h b/example/1d-heat-equation/cn/cpp/singleblock/01a/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/README.txt b/example/1d-heat-equation/cn/cpp/singleblock/01a/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/Solver.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01a/Solver.cpp new file mode 100644 index 00000000..563a40a3 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01a/Solver.cpp @@ -0,0 +1,730 @@ +#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; + this->scheme = Scheme::CN; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + 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::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( 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/cn/cpp/singleblock/01a/Solver.h b/example/1d-heat-equation/cn/cpp/singleblock/01a/Solver.h new file mode 100644 index 00000000..9b925249 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01a/Solver.h @@ -0,0 +1,65 @@ +#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, + CN, //Crank¨CNicolson + 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 CN(); + 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/cn/cpp/singleblock/01a/ZoneState.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01a/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/ZoneState.h b/example/1d-heat-equation/cn/cpp/singleblock/01a/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/global.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01a/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/global.h b/example/1d-heat-equation/cn/cpp/singleblock/01a/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/heat1d1block.cgns b/example/1d-heat-equation/cn/cpp/singleblock/01a/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/1d-heat-equation/cn/cpp/singleblock/01a/heat1d1block.cgns differ diff --git a/example/1d-heat-equation/cn/cpp/singleblock/01a/main.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01a/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01a/plot.py b/example/1d-heat-equation/cn/cpp/singleblock/01a/plot.py new file mode 100644 index 00000000..9a780526 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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="CN 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/cn/cpp/singleblock/01a/plotting2.jl b/example/1d-heat-equation/cn/cpp/singleblock/01a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/CMakeLists.txt b/example/1d-heat-equation/cn/cpp/singleblock/01b/CMakeLists.txt new file mode 100644 index 00000000..9e834b72 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/CgnsGrid.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01b/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/CgnsGrid.h b/example/1d-heat-equation/cn/cpp/singleblock/01b/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/Field.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01b/Field.cpp new file mode 100644 index 00000000..8f219225 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01b/Field.cpp @@ -0,0 +1,322 @@ +#include "Field.h" +#include "CgnsGrid.h" + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +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::CN( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + d[ ii ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +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 ]; + this->u[ ighost ] = - 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 ]; + this->u[ ighost ] = - 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/cn/cpp/singleblock/01b/Field.h b/example/1d-heat-equation/cn/cpp/singleblock/01b/Field.h new file mode 100644 index 00000000..a14588b8 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01b/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 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 CN( 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/cn/cpp/singleblock/01b/LogFile.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01b/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/LogFile.h b/example/1d-heat-equation/cn/cpp/singleblock/01b/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/Parallel.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01b/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/Parallel.h b/example/1d-heat-equation/cn/cpp/singleblock/01b/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/README.txt b/example/1d-heat-equation/cn/cpp/singleblock/01b/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/Solver.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01b/Solver.cpp new file mode 100644 index 00000000..563a40a3 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01b/Solver.cpp @@ -0,0 +1,730 @@ +#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; + this->scheme = Scheme::CN; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + 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::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( 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/cn/cpp/singleblock/01b/Solver.h b/example/1d-heat-equation/cn/cpp/singleblock/01b/Solver.h new file mode 100644 index 00000000..9b925249 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/01b/Solver.h @@ -0,0 +1,65 @@ +#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, + CN, //Crank¨CNicolson + 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 CN(); + 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/cn/cpp/singleblock/01b/ZoneState.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01b/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/ZoneState.h b/example/1d-heat-equation/cn/cpp/singleblock/01b/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/global.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01b/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/global.h b/example/1d-heat-equation/cn/cpp/singleblock/01b/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/heat1d1block.cgns b/example/1d-heat-equation/cn/cpp/singleblock/01b/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/1d-heat-equation/cn/cpp/singleblock/01b/heat1d1block.cgns differ diff --git a/example/1d-heat-equation/cn/cpp/singleblock/01b/main.cpp b/example/1d-heat-equation/cn/cpp/singleblock/01b/main.cpp new file mode 100644 index 00000000..df63b7da --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/cpp/singleblock/01b/plot.py b/example/1d-heat-equation/cn/cpp/singleblock/01b/plot.py new file mode 100644 index 00000000..9a780526 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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="CN 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/cn/cpp/singleblock/01b/plotting2.jl b/example/1d-heat-equation/cn/cpp/singleblock/01b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/cn/cpp/singleblock/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/cn/01/cn.py b/example/1d-heat-equation/cn/python/01/cn.py similarity index 100% rename from example/1d-heat-equation/cn/01/cn.py rename to example/1d-heat-equation/cn/python/01/cn.py diff --git a/example/1d-heat-equation/cn/02/cn.py b/example/1d-heat-equation/cn/python/02/cn.py similarity index 100% rename from example/1d-heat-equation/cn/02/cn.py rename to example/1d-heat-equation/cn/python/02/cn.py diff --git a/example/1d-heat-equation/icp/cpp/01/CMakeLists.txt b/example/1d-heat-equation/icp/cpp/01/CMakeLists.txt new file mode 100644 index 00000000..b7b5626e --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/01/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.31) + +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/icp/cpp/01/CgnsGrid.cpp b/example/1d-heat-equation/icp/cpp/01/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/CgnsGrid.h b/example/1d-heat-equation/icp/cpp/01/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/Field.cpp b/example/1d-heat-equation/icp/cpp/01/Field.cpp new file mode 100644 index 00000000..6b12aa17 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/01/Field.cpp @@ -0,0 +1,373 @@ +#include "Field.h" +#include "CgnsGrid.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +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::CN( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + d[ ii ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +void Field::ICP( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = ist; i <= ied; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + int ii = i - 1; + d[ ii ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +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 ]; + this->u[ ighost ] = - 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 ]; + this->u[ ighost ] = - 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/icp/cpp/01/Field.h b/example/1d-heat-equation/icp/cpp/01/Field.h new file mode 100644 index 00000000..2c9f2d23 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/01/Field.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "global.h" +#include "cgnslib.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 CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + 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 ); +}; diff --git a/example/1d-heat-equation/icp/cpp/01/LogFile.cpp b/example/1d-heat-equation/icp/cpp/01/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/LogFile.h b/example/1d-heat-equation/icp/cpp/01/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/Parallel.cpp b/example/1d-heat-equation/icp/cpp/01/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/Parallel.h b/example/1d-heat-equation/icp/cpp/01/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/README.txt b/example/1d-heat-equation/icp/cpp/01/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/Solver.cpp b/example/1d-heat-equation/icp/cpp/01/Solver.cpp new file mode 100644 index 00000000..72b2be32 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/01/Solver.cpp @@ -0,0 +1,749 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#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; + //this->scheme = Scheme::CN; + this->scheme = Scheme::ICP; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + 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::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( 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/icp/cpp/01/Solver.h b/example/1d-heat-equation/icp/cpp/01/Solver.h new file mode 100644 index 00000000..aaffe2b7 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/01/Solver.h @@ -0,0 +1,67 @@ +#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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + 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 CN(); + void ICP(); + 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/icp/cpp/01/ZoneState.cpp b/example/1d-heat-equation/icp/cpp/01/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/ZoneState.h b/example/1d-heat-equation/icp/cpp/01/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/global.cpp b/example/1d-heat-equation/icp/cpp/01/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/global.h b/example/1d-heat-equation/icp/cpp/01/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/heat1d1block.cgns b/example/1d-heat-equation/icp/cpp/01/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/1d-heat-equation/icp/cpp/01/heat1d1block.cgns differ diff --git a/example/1d-heat-equation/icp/cpp/01/main.cpp b/example/1d-heat-equation/icp/cpp/01/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/cpp/01/plot.py b/example/1d-heat-equation/icp/cpp/01/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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="ICP 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/icp/cpp/01/plotting2.jl b/example/1d-heat-equation/icp/cpp/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/1d-heat-equation/icp/cpp/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/icp/01/icp.py b/example/1d-heat-equation/icp/python/01/icp.py similarity index 100% rename from example/1d-heat-equation/icp/01/icp.py rename to example/1d-heat-equation/icp/python/01/icp.py diff --git a/example/1d-heat-equation/icp/02/icp.py b/example/1d-heat-equation/icp/python/02/icp.py similarity index 100% rename from example/1d-heat-equation/icp/02/icp.py rename to example/1d-heat-equation/icp/python/02/icp.py diff --git a/example/1d-heat-equation/icp/03/icp.py b/example/1d-heat-equation/icp/python/03/icp.py similarity index 100% rename from example/1d-heat-equation/icp/03/icp.py rename to example/1d-heat-equation/icp/python/03/icp.py diff --git a/example/inviscid-burgers-equation/grid/burgers1d1blocksv1.cgns b/example/inviscid-burgers-equation/grid/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/inviscid-burgers-equation/grid/burgers1d1blocksv1.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/CMakeLists.txt new file mode 100644 index 00000000..a382be60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/README.txt b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/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/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/main.cpp new file mode 100644 index 00000000..4111334e --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/main.cpp @@ -0,0 +1,308 @@ +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector> & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void rhs( int nx, double dx, std::vector & u, std::vector & r ); +void numerical( int nx, int ns, int nt, double dx, double dt, std::vector> & u ); + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int nx, std::vector & u, std::vector & f ) +{ + int i; + double v1, v2, v3, v4, v5; + + i = 0; + v1 = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + v2 = 2.0 * u[ i ] - u[ i + 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + + i = 1; + v1 = 2.0 * u[ i - 1 ] - u[ i ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + + for ( int i = 2; i < nx - 1; ++ i ) + { + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } + + i = nx - 1; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = 2.0 * u[ i + 1 ] - u[ i ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int nx, std::vector & u, std::vector & f ) +{ + int i; + double v1, v2, v3, v4, v5; + + i = 1; + v1 = 2.0 * u[ i - 1 ] - u[ i ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + for ( int i = 2; i < nx - 1; ++ i ) + { + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } + + i = nx - 1; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = 2.0 * u[ i + 1 ] - u[ i ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + + i = nx; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = 2.0 * u[ i ] - u[ i - 1 ]; + v5 = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int nx, double dx, std::vector & u, std::vector & r ) +{ + std::vector uL( nx, 0 ); + std::vector uR( nx + 1, 0 ); + + wenoL( nx, u, uL ); + wenoR( nx, u, uR ); + + for ( int i = 1; i < nx; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + r[ i ] = - u[ i ] * ( uL[ i ] - uL[ i - 1 ] ) / dx; + } + else + { + r[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical( int nx, int ns, int nt, double dx, double dt, std::vector> &u ) +{ + std::vector x( nx + 1, 0 ); + std::vector un( nx + 1, 0 ); // numerical solsution at every time step + std::vector ut( nx + 1, 0 ); // temporary array during RK3 integration + std::vector r( nx, 0 ); + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < nx + 1; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + u[ i ][ k ] = un[ i ]; //store solution at t = 0; + } + + //dirichlet boundary condition + u[ 0 ][ k ] = 0.0; + u[ nx ][ k ] = 0.0; + + un[ 0 ] = 0.0; + un[ nx ] = 0.0; + + //dirichlet boundary condition for temporary array + ut[ 0 ] = 0.0; + ut[ nx ] = 0.0; + + for ( int j = 1; j < nt + 1; ++ j ) + { + rhs( nx, dx, un, r ); + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = un[ i ] + dt * r[ i ]; + } + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * r[ i ]; + } + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * r[ i ]; + } + + if ( j % freq == 0 ) + { + k = k + 1; + for ( int i = 0; i < nx + 1; ++ i ) + { + u[ i ][ k ] = un[ i ]; + } + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector> &u ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + for ( int i = 0; i < u.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u[ i ].size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ i ][ j ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + + +int main( int argc, char ** argv ) +{ + int nx = 200; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / nx; + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "nx={}\n", nx ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + std::vector> u( nx + 1 ); + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].resize( ns + 1 ); + } + + numerical( nx, ns, nt, dx, dt, u ); + + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/plot.py b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/crweno5/cpp/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/inviscid-burgers-equation/non-conservative-form/crweno5/01/crweno5.py b/example/inviscid-burgers-equation/non-conservative-form/crweno5/python/01/crweno5.py similarity index 100% rename from example/inviscid-burgers-equation/non-conservative-form/crweno5/01/crweno5.py rename to example/inviscid-burgers-equation/non-conservative-form/crweno5/python/01/crweno5.py diff --git a/example/inviscid-burgers-equation/non-conservative-form/crweno5/02/crweno5.py b/example/inviscid-burgers-equation/non-conservative-form/crweno5/python/02/crweno5.py similarity index 100% rename from example/inviscid-burgers-equation/non-conservative-form/crweno5/02/crweno5.py rename to example/inviscid-burgers-equation/non-conservative-form/crweno5/python/02/crweno5.py diff --git a/example/inviscid-burgers-equation/non-conservative-form/crweno5/03/crweno5.py b/example/inviscid-burgers-equation/non-conservative-form/crweno5/python/03/crweno5.py similarity index 100% rename from example/inviscid-burgers-equation/non-conservative-form/crweno5/03/crweno5.py rename to example/inviscid-burgers-equation/non-conservative-form/crweno5/python/03/crweno5.py diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/0000002/weno5.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/0000002/weno5.py deleted file mode 100644 index c68cbad8..00000000 --- a/example/inviscid-burgers-equation/non-conservative-form/weno5/0000002/weno5.py +++ /dev/null @@ -1,272 +0,0 @@ -import numpy as np -import matplotlib.pyplot as plt - -#-----------------------------------------------------------------------------# -# Compute L-2 norm for a vector -#-----------------------------------------------------------------------------# -def compute_l2norm(nx,r): - rms = 0.0 - for i in range(1, nx): - rms += r[i] * r[i] - rms = np.sqrt( rms / ( ( nx - 1 ) ) ) - return rms - -#---------------------------------------------------------------------------# -#nonlinear weights for upwind direction -#---------------------------------------------------------------------------# -def wcL(v1,v2,v3,v4,v5): - eps = 1.0e-6 - - # smoothness indicators - s1 = (13.0/12.0)*(v1-2.0*v2+v3)**2 + 0.25*(v1-4.0*v2+3.0*v3)**2 - s2 = (13.0/12.0)*(v2-2.0*v3+v4)**2 + 0.25*(v2-v4)**2 - s3 = (13.0/12.0)*(v3-2.0*v4+v5)**2 + 0.25*(3.0*v3-4.0*v4+v5)**2 - - # computing nonlinear weights w1,w2,w3 - c1 = 1.0e-1 / ( (eps+s1)**2 ) - c2 = 6.0e-1 / ( (eps+s2)**2 ) - c3 = 3.0e-1 / ( (eps+s3)**2 ) - - w1 = c1/(c1+c2+c3) - w2 = c2/(c1+c2+c3) - w3 = c3/(c1+c2+c3) - - # candiate stencils - q1 = v1/3.0 - 7.0/6.0*v2 + 11.0/6.0*v3 - q2 =-v2/6.0 + 5.0/6.0*v3 + v4/3.0 - q3 = v3/3.0 + 5.0/6.0*v4 - v5/6.0 - - # reconstructed value at interface - f = (w1*q1 + w2*q2 + w3*q3) - - return f - - -#---------------------------------------------------------------------------# -#nonlinear weights for downwind direction -#---------------------------------------------------------------------------# -def wcR(v1,v2,v3,v4,v5): - eps = 1.0e-6 - - s1 = (13.0/12.0)*(v1-2.0*v2+v3)**2 + 0.25*(v1-4.0*v2+3.0*v3)**2 - s2 = (13.0/12.0)*(v2-2.0*v3+v4)**2 + 0.25*(v2-v4)**2 - s3 = (13.0/12.0)*(v3-2.0*v4+v5)**2 + 0.25*(3.0*v3-4.0*v4+v5)**2 - - c1 = 3.0e-1/(eps+s1)**2 - c2 = 6.0e-1/(eps+s2)**2 - c3 = 1.0e-1/(eps+s3)**2 - - w1 = c1/(c1+c2+c3) - w2 = c2/(c1+c2+c3) - w3 = c3/(c1+c2+c3) - - # candiate stencils - q1 =-v1/6.0 + 5.0/6.0*v2 + v3/3.0 - q2 = v2/3.0 + 5.0/6.0*v3 - v4/6.0 - q3 = 11.0/6.0*v3 - 7.0/6.0*v4 + v5/3.0 - - # reconstructed value at interface - f = (w1*q1 + w2*q2 + w3*q3) - - return f - -#-----------------------------------------------------------------------------# -# WENO reconstruction for upwind direction (positive; left to right) -# u(i): solution values at finite difference grid nodes i = 1,...,N+1 -# f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N -#-----------------------------------------------------------------------------# -def wenoL(nx,u,f): - a = np.zeros(nx) - b = np.zeros(nx) - c = np.zeros(nx) - r = np.zeros(nx) - - i = 0 - v1 = 3.0*u[i] - 2.0*u[i+1] - v2 = 2.0*u[i] - u[i+1] - v3 = u[i] - v4 = u[i+1] - v5 = u[i+2] - f[i] = wcL(v1,v2,v3,v4,v5) - - i = 1 - v1 = 2.0*u[i-1] - u[i] - v2 = u[i-1] - v3 = u[i] - v4 = u[i+1] - v5 = u[i+2] - f[i] = wcL(v1,v2,v3,v4,v5) - - for i in range(2, nx-1): - v1 = u[i-2] - v2 = u[i-1] - v3 = u[i] - v4 = u[i+1] - v5 = u[i+2] - f[i] = wcL(v1,v2,v3,v4,v5) - - i = nx-1 - v1 = u[i-2] - v2 = u[i-1] - v3 = u[i] - v4 = u[i+1] - v5 = 2.0*u[i+1]-u[i] - f[i] = wcL(v1,v2,v3,v4,v5) - -#-----------------------------------------------------------------------------# -# CRWENO reconstruction for downwind direction (negative; right to left) -# u(i): solution values at finite difference grid nodes i = 1,...,N+1 -# f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 -#-----------------------------------------------------------------------------# -def wenoR(n,u,f): - a = np.zeros(nx+1) - b = np.zeros(nx+1) - c = np.zeros(nx+1) - r = np.zeros(nx+1) - - i = 1 - v1 = 2.0*u[i-1] - u[i] - v2 = u[i-1] - v3 = u[i] - v4 = u[i+1] - v5 = u[i+2] - f[i] = wcR(v1,v2,v3,v4,v5) - - for i in range(2, nx-1): - v1 = u[i-2] - v2 = u[i-1] - v3 = u[i ] - v4 = u[i+1] - v5 = u[i+2] - f[i] = wcR(v1,v2,v3,v4,v5) - - i = nx-1 - v1 = u[i-2] - v2 = u[i-1] - v3 = u[i] - v4 = u[i+1] - v5 = 2.0*u[i+1] - u[i] - f[i] = wcR(v1,v2,v3,v4,v5) - - i = nx - v1 = u[i-2] - v2 = u[i-1] - v3 = u[i] - v4 = 2.0*u[i] - u[i-1] - v5 = 3.0*u[i] - 2.0*u[i-1] - f[i] = wcR(v1,v2,v3,v4,v5) - -#-----------------------------------------------------------------------------# -# Calculate right hand term of the inviscid Burgers equation -# r = -u∂u/∂x -#-----------------------------------------------------------------------------# -def rhs( nx, dx, u, r ): - uL = np.zeros( nx ) - uR = np.zeros( nx + 1 ) - - wenoL( nx, u, uL ) - wenoR( nx, u, uR ) - - for i in range(1, nx): - if ( u[i] >= 0.0 ): - r[i] = - u[i] * ( uL[i] - uL[i-1] ) / dx - else: - r[i] = - u[i] * ( uR[i+1] - uR[i] ) / dx - - #for i = 0; periodic - i = 0 - if ( u[i] >= 0.0 ): - r[i] = - u[i] * ( uL[i] - uL[nx-1] ) / dx - else: - r[i] = - u[i] * ( uR[i+1] - uR[nx] ) / dx - - -#-----------------------------------------------------------------------------# -# Compute numerical solution -# - Time integration using Runge-Kutta third order -# - 5th-order Compact WENO scheme for spatial terms -#-----------------------------------------------------------------------------# -def numerical( nx, ns, nt, dx, dt, u ): - x = np.zeros(nx+1) - un = np.zeros(nx+1) # numerical solsution at every time step - ut = np.zeros(nx+1) # temporary array during RK3 integration - r = np.zeros(nx) - - k = 0 # record index - freq = int( nt / ns ) - print("freq=",freq) - - for i in range(0, nx+1): - x[i] = dx * ( i ) - un[i] = np.sin( 2.0 * np.pi * x[i] ) - u[i,k] = un[i] # store solution at t=0 - - # dirichlet boundary condition - u[0 ,k] = 0.0 - u[nx,k] = 0.0 - - un[0 ] = 0.0 - un[nx] = 0.0 - - # dirichlet boundary condition for temporary array - ut[0 ] = 0.0 - ut[nx] = 0.0 - - for j in range(1, nt+1): - rhs( nx, dx, un, r ) - - for i in range(1, nx): - ut[i] = un[i] + dt*r[i] - - ut[nx] = ut[0] # periodic - - rhs( nx, dx, ut, r) - - for i in range(1, nx): - ut[i] = 0.75*un[i] + 0.25*ut[i] + 0.25*dt*r[i] - - ut[nx] = ut[0] # periodic - - rhs( nx, dx, ut, r ) - - for i in range(1, nx): - un[i] = (1.0/3.0)*un[i] + (2.0/3.0)*ut[i] + (2.0/3.0)*dt*r[i] - - ut[nx] = ut[0] # periodic - - if ( j% freq == 0 ): - k = k+1 - u[:,k] = un[:] - print("k=",k,"ns=",ns) - -nx = 200 -ns = 10 -dt = 0.0001 -tm = 0.25 - -dx = 1.0 / nx -nt = int( tm / dt ) -ds = tm / ns - -print("nx=",nx) -print("ns=",ns) -print("dt=",dt) -print("tm=",tm) -print("dx=",dx) -print("nt=",nt) - -u = np.zeros( (nx+1, ns+1 ) ) -numerical( nx, ns, nt, dx, dt, u ) - -x = np.linspace(0,1, num=nx+1) - -plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) -for k in range(0, ns+1): - plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) -plt.xlabel("$x$") -plt.ylabel("$u$") -plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") -plt.legend(loc='upper right', fontsize='6') -plt.show() - - diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/CMakeLists.txt new file mode 100644 index 00000000..a382be60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/main.cpp new file mode 100644 index 00000000..4111334e --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/main.cpp @@ -0,0 +1,308 @@ +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +void DumpCsvFile( const std::string & filename, std::vector & x, std::vector> & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void rhs( int nx, double dx, std::vector & u, std::vector & r ); +void numerical( int nx, int ns, int nt, double dx, double dt, std::vector> & u ); + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int nx, std::vector & u, std::vector & f ) +{ + int i; + double v1, v2, v3, v4, v5; + + i = 0; + v1 = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + v2 = 2.0 * u[ i ] - u[ i + 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + + i = 1; + v1 = 2.0 * u[ i - 1 ] - u[ i ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + + for ( int i = 2; i < nx - 1; ++ i ) + { + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } + + i = nx - 1; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = 2.0 * u[ i + 1 ] - u[ i ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int nx, std::vector & u, std::vector & f ) +{ + int i; + double v1, v2, v3, v4, v5; + + i = 1; + v1 = 2.0 * u[ i - 1 ] - u[ i ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + for ( int i = 2; i < nx - 1; ++ i ) + { + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } + + i = nx - 1; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = 2.0 * u[ i + 1 ] - u[ i ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + + i = nx; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = 2.0 * u[ i ] - u[ i - 1 ]; + v5 = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int nx, double dx, std::vector & u, std::vector & r ) +{ + std::vector uL( nx, 0 ); + std::vector uR( nx + 1, 0 ); + + wenoL( nx, u, uL ); + wenoR( nx, u, uR ); + + for ( int i = 1; i < nx; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + r[ i ] = - u[ i ] * ( uL[ i ] - uL[ i - 1 ] ) / dx; + } + else + { + r[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical( int nx, int ns, int nt, double dx, double dt, std::vector> &u ) +{ + std::vector x( nx + 1, 0 ); + std::vector un( nx + 1, 0 ); // numerical solsution at every time step + std::vector ut( nx + 1, 0 ); // temporary array during RK3 integration + std::vector r( nx, 0 ); + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < nx + 1; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + u[ i ][ k ] = un[ i ]; //store solution at t = 0; + } + + //dirichlet boundary condition + u[ 0 ][ k ] = 0.0; + u[ nx ][ k ] = 0.0; + + un[ 0 ] = 0.0; + un[ nx ] = 0.0; + + //dirichlet boundary condition for temporary array + ut[ 0 ] = 0.0; + ut[ nx ] = 0.0; + + for ( int j = 1; j < nt + 1; ++ j ) + { + rhs( nx, dx, un, r ); + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = un[ i ] + dt * r[ i ]; + } + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * r[ i ]; + } + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * r[ i ]; + } + + if ( j % freq == 0 ) + { + k = k + 1; + for ( int i = 0; i < nx + 1; ++ i ) + { + u[ i ][ k ] = un[ i ]; + } + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, std::vector &x, std::vector> &u ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + for ( int i = 0; i < u.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u[ i ].size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ i ][ j ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + + +int main( int argc, char ** argv ) +{ + int nx = 200; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / nx; + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "nx={}\n", nx ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + std::vector> u( nx + 1 ); + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].resize( ns + 1 ); + } + + numerical( nx, ns, nt, dx, dt, u ); + + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/CMakeLists.txt new file mode 100644 index 00000000..a382be60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/main.cpp new file mode 100644 index 00000000..bea651f4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/main.cpp @@ -0,0 +1,349 @@ +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } +}; + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector> & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int nx, vec1d & u, vec1d & f ); +void wenoR( int nx, vec1d & u, vec1d & f ); +void rhs( int nx, double dx, vec1d & u, vec1d & r ); +void numerical( int nx, int ns, int nt, double dx, double dt ); + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int nx, vec1d & u, vec1d & f ) +{ + int i; + double v1, v2, v3, v4, v5; + + i = 0; + v1 = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + v2 = 2.0 * u[ i ] - u[ i + 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + + i = 1; + v1 = 2.0 * u[ i - 1 ] - u[ i ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + + for ( int i = 2; i < nx - 1; ++ i ) + { + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } + + i = nx - 1; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = 2.0 * u[ i + 1 ] - u[ i ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int nx, vec1d & u, vec1d & f ) +{ + int i; + double v1, v2, v3, v4, v5; + + i = 1; + v1 = 2.0 * u[ i - 1 ] - u[ i ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + for ( int i = 2; i < nx - 1; ++ i ) + { + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } + + i = nx - 1; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = 2.0 * u[ i + 1 ] - u[ i ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + + i = nx; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = 2.0 * u[ i ] - u[ i - 1 ]; + v5 = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int nx, double dx, vec1d & u, vec1d & r ) +{ + //std::vector uL( nx, 0 ); + //std::vector uR( nx + 1, 0 ); + + vec1d uL; + uL.Allocate( 0, nx - 1, 0 ); + + vec1d uR; + uR.Allocate( 0, nx, 0 ); + + wenoL( nx, u, uL ); + wenoR( nx, u, uR ); + + for ( int i = 1; i < nx; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + r[ i ] = - u[ i ] * ( uL[ i ] - uL[ i - 1 ] ) / dx; + } + else + { + r[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical( int nx, int ns, int nt, double dx, double dt ) +{ + std::vector> u( nx + 1 ); + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].resize( ns + 1 ); + } + + //std::vector x( nx + 1, 0 ); + + vec1d x; + x.Allocate( 0, nx, 0 ); // numerical solsution at every time step + + vec1d un; + un.Allocate( 0, nx, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( 0, nx, 0 ); // temporary array during RK3 integration + + vec1d r; + r.Allocate( 0, nx - 1, 0 ); + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < nx + 1; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + u[ i ][ k ] = un[ i ]; //store solution at t = 0; + } + + //dirichlet boundary condition + u[ 0 ][ k ] = 0.0; + u[ nx ][ k ] = 0.0; + + un[ 0 ] = 0.0; + un[ nx ] = 0.0; + + //dirichlet boundary condition for temporary array + ut[ 0 ] = 0.0; + ut[ nx ] = 0.0; + + for ( int j = 1; j < nt + 1; ++ j ) + { + rhs( nx, dx, un, r ); + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = un[ i ] + dt * r[ i ]; + } + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * r[ i ]; + } + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * r[ i ]; + } + + if ( j % freq == 0 ) + { + k = k + 1; + for ( int i = 0; i < nx + 1; ++ i ) + { + u[ i ][ k ] = un[ i ]; + } + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector> &u ) +{ + std::fstream file; + file.open(filename.c_str(), std::fstream::out); + for ( int i = 0; i < u.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u[ i ].size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ i ][ j ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + + +int main( int argc, char ** argv ) +{ + int nx = 200; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / nx; + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "nx={}\n", nx ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + numerical( nx, ns, nt, dx, dt ); + + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/CMakeLists.txt new file mode 100644 index 00000000..a382be60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/main.cpp new file mode 100644 index 00000000..94db965a --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/main.cpp @@ -0,0 +1,355 @@ +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } +}; + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int nx, vec1d & u, vec1d & f ); +void wenoR( int nx, vec1d & u, vec1d & f ); +void rhs( int nx, double dx, vec1d & u, vec1d & r ); +void numerical( int nx, int ns, int nt, double dx, double dt ); + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int nx, vec1d & u, vec1d & f ) +{ + int i; + double v1, v2, v3, v4, v5; + + i = 0; + v1 = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + v2 = 2.0 * u[ i ] - u[ i + 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + + i = 1; + v1 = 2.0 * u[ i - 1 ] - u[ i ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + + for ( int i = 2; i < nx - 1; ++ i ) + { + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } + + i = nx - 1; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = 2.0 * u[ i + 1 ] - u[ i ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int nx, vec1d & u, vec1d & f ) +{ + int i; + double v1, v2, v3, v4, v5; + + i = 1; + v1 = 2.0 * u[ i - 1 ] - u[ i ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + for ( int i = 2; i < nx - 1; ++ i ) + { + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = u[ i + 2 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } + + i = nx - 1; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = u[ i + 1 ]; + v5 = 2.0 * u[ i + 1 ] - u[ i ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + + i = nx; + v1 = u[ i - 2 ]; + v2 = u[ i - 1 ]; + v3 = u[ i ]; + v4 = 2.0 * u[ i ] - u[ i - 1 ]; + v5 = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int nx, double dx, vec1d & u, vec1d & r ) +{ + vec1d uL; + uL.Allocate( 0, nx - 1, 0 ); + + vec1d uR; + uR.Allocate( 0, nx, 0 ); + + wenoL( nx, u, uL ); + wenoR( nx, u, uR ); + + for ( int i = 1; i < nx; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + r[ i ] = - u[ i ] * ( uL[ i ] - uL[ i - 1 ] ) / dx; + } + else + { + r[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical( int nx, int ns, int nt, double dx, double dt ) +{ + //std::vector u( nx + 1 ); + std::vector u( ns + 1 ); + + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].Allocate( 0, nx ); + } + + vec1d x; + x.Allocate( 0, nx, 0 ); // npoints = N = nx + 1 + + //int ighost = 2; + int ighost = 0; + int ist = 0 - ighost; + int ied = nx + ighost; + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d r; + r.Allocate( 0, nx - 1, 0 ); + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < nx + 1; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + u[ k ][ i ] = un[ i ]; //store solution at t = 0; + } + + //dirichlet boundary condition + u[ k ][ 0 ] = 0.0; + u[ k ][ nx ] = 0.0; + + un[ 0 ] = 0.0; + un[ nx ] = 0.0; + + //dirichlet boundary condition for temporary array + ut[ 0 ] = 0.0; + ut[ nx ] = 0.0; + + for ( int j = 1; j < nt + 1; ++ j ) + { + rhs( nx, dx, un, r ); + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = un[ i ] + dt * r[ i ]; + } + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * r[ i ]; + } + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * r[ i ]; + } + + if ( j % freq == 0 ) + { + k = k + 1; + for ( int i = 0; i < nx + 1; ++ i ) + { + u[ k ][ i ] = un[ i ]; + } + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + + +int main( int argc, char ** argv ) +{ + int nx = 200; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / nx; + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "nx={}\n", nx ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + numerical( nx, ns, nt, dx, dt ); + + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/CMakeLists.txt new file mode 100644 index 00000000..a382be60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/main.cpp new file mode 100644 index 00000000..4e2244d7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/main.cpp @@ -0,0 +1,314 @@ +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int nx, vec1d & u, vec1d & f ); +void wenoR( int nx, vec1d & u, vec1d & f ); +void rhs( int nx, double dx, vec1d & u, vec1d & r ); +void numerical( int nx, int ns, int nt, double dx, double dt ); + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int nx, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= nx - 1; ++ i ) + { + double v1 = u[ i - 2 ]; + double v2 = u[ i - 1 ]; + double v3 = u[ i ]; + double v4 = u[ i + 1 ]; + double v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int nx, vec1d & u, vec1d & f ) +{ + for ( int i = 1; i <= nx; ++ i ) + { + double v1 = u[ i - 2 ]; + double v2 = u[ i - 1 ]; + double v3 = u[ i ]; + double v4 = u[ i + 1 ]; + double v5 = u[ i + 2 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int nx, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + //right bc + i = nx; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int nx, double dx, vec1d & u, vec1d & r ) +{ + vec1d uL; + uL.Allocate( 0, nx - 1, 0 ); + + vec1d uR; + uR.Allocate( 0, nx, 0 ); + + wenoL( nx, u, uL ); + wenoR( nx, u, uR ); + + for ( int i = 1; i < nx; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + r[ i ] = - u[ i ] * ( uL[ i ] - uL[ i - 1 ] ) / dx; + } + else + { + r[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical( int nx, int ns, int nt, double dx, double dt ) +{ + vec1d x; + x.Allocate( 0, nx, 0 ); // npoints = N = nx + 1 + + int ighost = 2; + //int ighost = 0; + int ist = 0 - ighost; + int ied = nx + ighost; + + std::vector u( ns + 1 ); + + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d r; + r.Allocate( 0, nx - 1, 0 ); + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < nx + 1; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( nx, un ); + u[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + rhs( nx, dx, un, r ); + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = un[ i ] + dt * r[ i ]; + } + boundary( nx, ut ); + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * r[ i ]; + } + boundary( nx, ut ); + rhs( nx, dx, ut, r ); + + for ( int i = 1; i < nx; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * r[ i ]; + } + boundary( nx, un ); + + if ( it % freq == 0 ) + { + k = k + 1; + u[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + + +int main( int argc, char ** argv ) +{ + int nx = 200; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / nx; + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "nx={}\n", nx ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + numerical( nx, ns, nt, dx, dt ); + + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01c/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/CMakeLists.txt new file mode 100644 index 00000000..a382be60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/main.cpp new file mode 100644 index 00000000..f77a1152 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/main.cpp @@ -0,0 +1,314 @@ +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int nx, vec1d & u, vec1d & f ); +void wenoR( int nx, vec1d & u, vec1d & f ); +void rhs( int nx, double dx, vec1d & u, vec1d & r ); +void numerical( int nx, int ns, int nt, double dx, double dt ); + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int nx, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= nx - 1; ++ i ) + { + double v1 = u[ i - 2 ]; + double v2 = u[ i - 1 ]; + double v3 = u[ i ]; + double v4 = u[ i + 1 ]; + double v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int nx, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= nx - 1; ++ i ) + { + double v1 = u[ i - 1 ]; + double v2 = u[ i ]; + double v3 = u[ i + 1 ]; + double v4 = u[ i + 2 ]; + double v5 = u[ i + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int nx, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + //right bc + i = nx; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int nx, double dx, vec1d & u, vec1d & res ) +{ + vec1d uL; + uL.Allocate( 0, nx - 1, 0 ); + + vec1d uR; + uR.Allocate( 0, nx - 1, 0 ); + + wenoL( nx, u, uL ); + wenoR( nx, u, uR ); + + for ( int i = 1; i < nx; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i ] - uL[ i - 1 ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i ] - uR[ i - 1 ] ) / dx; + } + } +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical( int nx, int ns, int nt, double dx, double dt ) +{ + vec1d x; + x.Allocate( 0, nx, 0 ); // npoints = N = nx + 1 + + int ighost = 2; + //int ighost = 0; + int ist = 0 - ighost; + int ied = nx + ighost; + + std::vector u( ns + 1 ); + + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d res; + res.Allocate( 0, nx - 1, 0 ); + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < nx + 1; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( nx, un ); + u[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + rhs( nx, dx, un, res ); + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( nx, ut ); + rhs( nx, dx, ut, res ); + + for ( int i = 1; i < nx; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( nx, ut ); + rhs( nx, dx, ut, res ); + + for ( int i = 1; i < nx; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( nx, un ); + + if ( it % freq == 0 ) + { + k += 1; + u[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + + +int main( int argc, char ** argv ) +{ + int nx = 200; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / nx; + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "nx={}\n", nx ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + numerical( nx, ns, nt, dx, dt ); + + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01d/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/CMakeLists.txt new file mode 100644 index 00000000..a382be60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/main.cpp new file mode 100644 index 00000000..e5b50535 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/main.cpp @@ -0,0 +1,316 @@ +#include +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, vec1d & u, vec1d & f ); +void wenoR( int N, vec1d & u, vec1d & f ); +void rhs( int N, double dx, vec1d & u, vec1d & r ); +void boundary( int N, vec1d & u ); +void numerical( int N, int ns, int nt, double dx, double dt ); + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N - 2; ++ i ) + { + double v1 = u[ i - 2 ]; + double v2 = u[ i - 1 ]; + double v3 = u[ i ]; + double v4 = u[ i + 1 ]; + double v5 = u[ i + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N - 2; ++ i ) + { + double v1 = u[ i - 1 ]; + double v2 = u[ i ]; + double v3 = u[ i + 1 ]; + double v4 = u[ i + 2 ]; + double v5 = u[ i + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, vec1d & u, vec1d & res ) +{ + vec1d uL; + uL.Allocate( 0, N - 2, 0 ); + + vec1d uR; + uR.Allocate( 0, N - 2, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 1; i < N - 1; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i ] - uL[ i - 1 ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i ] - uR[ i - 1 ] ) / dx; + } + } +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical( int N, int ns, int nt, double dx, double dt ) +{ + vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 2; + //int ighost = 0; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector u( ns + 1 ); + + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d res; + res.Allocate( 0, N - 2, 0 ); + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + u[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + rhs( N, dx, un, res ); + for ( int i = 1; i < N - 1; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, ut ); + rhs( N, dx, ut, res ); + + for ( int i = 1; i < N - 1; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, ut ); + rhs( N, dx, ut, res ); + + for ( int i = 1; i < N - 1; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, un ); + + if ( it % freq == 0 ) + { + k += 1; + u[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + + +int main( int argc, char ** argv ) +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + numerical( N, ns, nt, dx, dt ); + + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01e/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/CMakeLists.txt new file mode 100644 index 00000000..a382be60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/main.cpp new file mode 100644 index 00000000..0f530bff --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/main.cpp @@ -0,0 +1,317 @@ +#include +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, vec1d & u, vec1d & f ); +void wenoR( int N, vec1d & u, vec1d & f ); +void rhs( int N, double dx, vec1d & u, vec1d & r ); +void boundary( int N, vec1d & u ); +void numerical( int N, int ns, int nt, double dx, double dt ); + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, vec1d & u, vec1d & res ) +{ + vec1d uL; + uL.Allocate( 0, N, 0 ); + + vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical( int N, int ns, int nt, double dx, double dt ) +{ + vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector u( ns + 1 ); + + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + u[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + rhs( N, dx, un, res ); + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, ut ); + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, ut ); + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, un ); + + if ( it % freq == 0 ) + { + k += 1; + u[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + + +int main( int argc, char ** argv ) +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + numerical( N, ns, nt, dx, dt ); + + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01f/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/CMakeLists.txt new file mode 100644 index 00000000..a382be60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/main.cpp new file mode 100644 index 00000000..c9b223b4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/main.cpp @@ -0,0 +1,341 @@ +#include +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, vec1d & u, vec1d & f ); +void wenoR( int N, vec1d & u, vec1d & f ); +void rhs( int N, double dx, vec1d & u, vec1d & r ); +void boundary( int N, vec1d & u ); +void numerical(); + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, vec1d & u, vec1d & res ) +{ + vec1d uL; + uL.Allocate( 0, N, 0 ); + + vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, ut, res, dx, dt ); + runge_kutta_stage2( N, un, ut, res, dx, dt ); + runge_kutta_stage3( N, un, ut, res, dx, dt ); +} + +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, un, res ); + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, un ); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector u( ns + 1 ); + + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + u[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, ut, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + u[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + + +int main( int argc, char ** argv ) +{ + numerical(); + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/01g/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/CMakeLists.txt new file mode 100644 index 00000000..f4e3e147 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/Solver.cpp new file mode 100644 index 00000000..7f6ac38b --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/Solver.cpp @@ -0,0 +1,292 @@ +#include "Solver.h" + +Solver::Solver() +{ + ; +} + +Solver::~Solver() +{ + ; +} + +void Solver::Solve() +{ + numerical(); +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 3 ] = 4.0 * u[ i ] - 3.0 * u[ i + 1 ]; + + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + u[ i + 3 ] = 4.0 * u[ i ] - 3.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, vec1d & u, vec1d & res ) +{ + vec1d uL; + uL.Allocate( 0, N, 0 ); + + vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, ut, res, dx, dt ); + runge_kutta_stage2( N, un, ut, res, dx, dt ); + runge_kutta_stage3( N, un, ut, res, dx, dt ); +} + +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, un, res ); + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, un ); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector u( ns + 1 ); + + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + u[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, ut, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + u[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/Solver.h new file mode 100644 index 00000000..af6cdfe8 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/Solver.h @@ -0,0 +1,72 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, vec1d & u, vec1d & f ); +void wenoR( int N, vec1d & u, vec1d & f ); +void rhs( int N, double dx, vec1d & u, vec1d & r ); +void boundary( int N, vec1d & u ); +void numerical(); + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Solve(); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/main.cpp new file mode 100644 index 00000000..742667fc --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/main.cpp @@ -0,0 +1,344 @@ +#include "Solver.h" +//#include +//#include +//#include +//#include +//#include +//#include +// +//template +//auto SQR(Args... args) { +// return (... + (args * args)); +//} +// +//class vec1d +//{ +//public: +// std::vector data; +// int ist = 0; +//public: +// void Allocate( int ist, int ied, double value = 0 ) +// { +// int nelement = ied - ist + 1; +// this->data.resize( nelement, value ); +// this->ist = ist; +// } +// std::size_t size() +// { +// return this->data.size(); +// } +// +// double operator [] ( int i ) const +// { +// return data[ i - ist ]; +// } +// +// double & operator [] ( int i ) +// { +// return data[ i - ist ]; +// } +// +// vec1d & operator = ( const vec1d & rhs ) +// { +// if ( this == & rhs ) return * this; +// this->data = rhs.data; +// +// return * this; +// } +//}; +// +//void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +//double wcL( double v1, double v2, double v3, double v4, double v5 ); +//double wcR( double v1, double v2, double v3, double v4, double v5 ); +//void wenoL( int N, vec1d & u, vec1d & f ); +//void wenoR( int N, vec1d & u, vec1d & f ); +//void rhs( int N, double dx, vec1d & u, vec1d & r ); +//void boundary( int N, vec1d & u ); +//void numerical(); +// +//void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +//void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +//void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +//void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +// +//double wcL( double v1, double v2, double v3, double v4, double v5 ) +//{ +// double eps = 1.0e-6; +// +// // smoothness indicators +// double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); +// double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); +// double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); +// +// // computing nonlinear weights w1, w2, w3 +// double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); +// double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); +// double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); +// +// double w1 = c1 / ( c1 + c2 + c3 ); +// double w2 = c2 / ( c1 + c2 + c3 ); +// double w3 = c3 / ( c1 + c2 + c3 ); +// +// // candiate stencils +// double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; +// double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; +// double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; +// +// // reconstructed value at interface +// double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); +// +// return f; +//} +// +//double wcR( double v1, double v2, double v3, double v4, double v5 ) +//{ +// double eps = 1.0e-6; +// +// // smoothness indicators +// double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); +// double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); +// double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); +// +// // computing nonlinear weights w1, w2, w3 +// double c1 = 3.0e-1 / SQR( eps + s1 ); +// double c2 = 6.0e-1 / SQR( eps + s2 ); +// double c3 = 1.0e-1 / SQR( eps + s3 ); +// +// double w1 = c1 / ( c1 + c2 + c3 ); +// double w2 = c2 / ( c1 + c2 + c3 ); +// double w3 = c3 / ( c1 + c2 + c3 ); +// +// // candiate stencils; +// double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; +// double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; +// double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; +// +// // reconstructed value at interface +// double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); +// +// return f; +//} +// +////----------------------------------------------------------------------------- +//// WENO reconstruction for upwind direction (positive; left to right) +//// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +//// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +////----------------------------------------------------------------------------- +//void wenoL( int N, vec1d & u, vec1d & f ) +//{ +// for ( int i = 0; i <= N; ++ i ) +// { +// int ii = i - 1; +// double v1 = u[ ii - 2 ]; +// double v2 = u[ ii - 1 ]; +// double v3 = u[ ii ]; +// double v4 = u[ ii + 1 ]; +// double v5 = u[ ii + 2 ]; +// f[ i ] = wcL( v1, v2, v3, v4, v5 ); +// } +//} +// +////----------------------------------------------------------------------------- +//// CRWENO reconstruction for downwind direction (negative; right to left) +//// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +//// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +////----------------------------------------------------------------------------- +//void wenoR( int N, vec1d & u, vec1d & f ) +//{ +// for ( int i = 0; i <= N; ++ i ) +// { +// int ii = i - 1; +// double v1 = u[ ii - 1 ]; +// double v2 = u[ ii ]; +// double v3 = u[ ii + 1 ]; +// double v4 = u[ ii + 2 ]; +// double v5 = u[ ii + 3 ]; +// f[ i ] = wcR( v1, v2, v3, v4, v5 ); +// } +//} +// +//void boundary( int N, vec1d & u ) +//{ +// //left bc +// int i = 0; +// u[ i ] = 0.0; +// u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; +// u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; +// //right bc +// i = N - 1; +// u[ i ] = 0.0; +// u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; +// u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; +//} +// +////----------------------------------------------------------------------------- +//// Calculate right hand term of the inviscid Burgers equation +////----------------------------------------------------------------------------- +//void rhs( int N, double dx, vec1d & u, vec1d & res ) +//{ +// vec1d uL; +// uL.Allocate( 0, N, 0 ); +// +// vec1d uR; +// uR.Allocate( 0, N, 0 ); +// +// wenoL( N, u, uL ); +// wenoR( N, u, uR ); +// +// for ( int i = 0; i < N; ++ i ) +// { +// if ( u[ i ] >= 0.0 ) +// { +// res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; +// } +// else +// { +// res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; +// } +// } +//} +// +//void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +//{ +// runge_kutta_stage1( N, un, ut, res, dx, dt ); +// runge_kutta_stage2( N, un, ut, res, dx, dt ); +// runge_kutta_stage3( N, un, ut, res, dx, dt ); +//} +// +//void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +//{ +// rhs( N, dx, un, res ); +// for ( int i = 0; i < N; ++ i ) +// { +// ut[ i ] = un[ i ] + dt * res[ i ]; +// } +// boundary( N, ut ); +//} +// +//void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +//{ +// rhs( N, dx, ut, res ); +// +// for ( int i = 0; i < N; ++ i ) +// { +// ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; +// } +// boundary( N, ut ); +//} +// +//void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +//{ +// rhs( N, dx, ut, res ); +// +// for ( int i = 0; i < N; ++ i ) +// { +// un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; +// } +// boundary( N, un ); +//} +// +////----------------------------------------------------------------------------- +//// Compute numerical solution +//// - Time integration using Runge-Kutta third order +//// - 5th-order Compact WENO scheme for spatial terms +////----------------------------------------------------------------------------- +//void numerical() +//{ +// int N = 201; +// int ns = 10; +// double dt = 0.0001; +// double tm = 0.25; +// +// double dx = 1.0 / ( N - 1 ); +// int nt = std::round( tm / dt ); +// double ds = tm / ns; +// +// std::print( "Npoints={}\n", N ); +// std::print( "ns={}\n", ns ); +// std::print( "dt={}\n", dt ); +// std::print( "tm={}\n", tm ); +// std::print( "dx={}\n", dx ); +// std::print( "nt={}\n", nt ); +// +// vec1d x; +// x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 +// +// int ighost = 3; +// int ist = 0 - ighost; +// int ied = N - 1 + ighost; +// +// std::vector u( ns + 1 ); +// +// for ( int i = 0; i < u.size(); ++ i ) +// { +// u[ i ].Allocate( ist, ied, 0 ); +// } +// +// vec1d un; +// un.Allocate( ist, ied, 0 ); // numerical solsution at every time step +// +// vec1d ut; +// ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration +// +// vec1d res; +// res.Allocate( 0, N, 0 ); //N+1 +// +// int k = 0; // record index +// int freq = std::round( nt / ns ); +// std::print( "freq = {}\n", freq ); +// +// for ( int i = 0; i < N; ++ i ) +// { +// x[ i ] = dx * ( i ); +// un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); +// } +// +// boundary( N, un ); +// u[ k ] = un; //store solution at t = 0; +// +// for ( int it = 1; it <= nt; ++ it ) +// { +// runge_kutta( N, un, ut, res, dx, dt ); +// +// if ( it % freq == 0 ) +// { +// k += 1; +// u[ k ] = un; +// std::print( "k={}, ns={}\n", k, ns ); +// } +// } +// +// DumpCsvFile( "field_final.csv", x, u ); +//} +// +//void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +//{ +// std::fstream file; +// file.open( filename.c_str(), std::fstream::out ); +// for ( int i = 0; i < x.size(); ++ i ) +// { +// std::string str = {}; +// str += std::format( "{:.16f} ", x[ i ] ); +// int nj = u.size(); +// for ( int j = 0; j < nj; ++ j ) +// { +// double value = u[ j ][ i ]; +// str += std::format( "{:.16f}", value ); +// if ( j != nj - 1 ) +// { +// str += " "; +// } +// } +// std::format_to(std::ostream_iterator(file), "{}\n", str ); +// } +// file.close(); +//} + + +int main( int argc, char ** argv ) +{ + //numerical(); + Solver solver; + solver.Solve(); + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/CMakeLists.txt new file mode 100644 index 00000000..51402052 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/CMakeLists.txt @@ -0,0 +1,100 @@ +cmake_minimum_required(VERSION 3.31) + +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 + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/CgnsGrid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/CgnsGrid.cpp new file mode 100644 index 00000000..825442a2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/CgnsGrid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/CgnsGrid.h new file mode 100644 index 00000000..fddf1db6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Field.cpp new file mode 100644 index 00000000..a248515a --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Field.cpp @@ -0,0 +1,422 @@ +#include "Field.h" +#include "CgnsGrid.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +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::CN( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + d[ ii ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +void Field::ICP( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = ist; i <= ied; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + int ii = i - 1; + d[ ii ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +void Field::WENO5( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = ist; i <= ied; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + int ii = i - 1; + d[ ii ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +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 ]; + this->u[ ighost ] = - 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 ]; + this->u[ ighost ] = - 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Field.h new file mode 100644 index 00000000..a7dc4658 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Field.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "global.h" +#include "cgnslib.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 CN( Zone * zone ); + void ICP( Zone * zone ); + void WENO5( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Solver.cpp new file mode 100644 index 00000000..e7b5134e --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Solver.cpp @@ -0,0 +1,773 @@ +#include "Solver.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "global.h" +#include "Weno.h" +#include +#include +#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; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO5; + + //std::cout << sum(1, 2, 3, 4, 5) << std::endl; // Êä³ö£º15 + //std::cout << SQR( 1, 1 ) << std::endl; + //std::cout << SQR( 2 ) << std::endl; + //std::cout << SQR( 2, 3 ) << std::endl; + int kkk = 1; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + 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::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO5: + this->WENO5(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::WENO5() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->WENO5( 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Solver.h new file mode 100644 index 00000000..ebf64f09 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Solver.h @@ -0,0 +1,69 @@ +#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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO5, //Weighted Essentially Non-Oscillatory (WENO) Schemes + 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 CN(); + void ICP(); + void WENO5(); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Weno.cpp new file mode 100644 index 00000000..c153be32 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Weno.cpp @@ -0,0 +1,141 @@ +#include "Weno.h" +#include + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, std::vector & u, std::vector & f ) +{ + int igL = 2; + int igR = 2; + int ist = igL; + int ied = ist + N - 1; + //for ( int i = ist + 1; i <= ied; ++ i ) + //{ + // int ii = i - ist - 1; + for ( int i = ist; i <= ied - 1; ++ i ) + { + int ii = i - ist; + double v1 = u[ i - 2 ]; + double v2 = u[ i - 1 ]; + double v3 = u[ i ]; + double v4 = u[ i + 1 ]; + double v5 = u[ i + 2 ]; + f[ ii ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, std::vector & u, std::vector & f ) +{ + int igL = 2; + int igR = 2; + int ist = igL; + int ied = ist + N - 1; + for ( int i = ist + 1; i <= ied; ++ i ) + { + int ii = i - ist - 1; + double v1 = u[ i - 2 ]; + double v2 = u[ i - 1 ]; + double v3 = u[ i ]; + double v4 = u[ i + 1 ]; + double v5 = u[ i + 2 ]; + f[ ii ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void WenoRhs( int N, double dx, std::vector & u, std::vector & r ) +{ + std::vector uL( N - 1, 0 ); + std::vector uR( N - 1, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + int igL = 2; + int igR = 2; + int ist = igL; + int ied = ist + N - 1; + + //1~N-2:3~N + //ist+1->ied-1 + + for ( int i = ist + 1; i <= ied - 1; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + r[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + r[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Weno.h new file mode 100644 index 00000000..18ee0faf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/Weno.h @@ -0,0 +1,20 @@ +#pragma once +#include + +template +auto sum(Args... args) { + return (... + args); +} + +template +auto SQR(Args... args) { + return (... + (args * args)); // ʹÓÃÕÛµþ±í´ïʽ¼ÆËãÆ½·½ºÍ +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); + +void wenoL( int N, std::vector & u, std::vector & f ); +void wenoR( int N, std::vector & u, std::vector & f ); +void WenoRhs( int N, double dx, std::vector & u, std::vector & r ); + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/global.cpp new file mode 100644 index 00000000..df1e6bae --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/global.h new file mode 100644 index 00000000..933cec05 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/heat1d1block.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/heat1d1block.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/020000000/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/CMakeLists.txt new file mode 100644 index 00000000..bc21067b --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Field.cpp new file mode 100644 index 00000000..10142909 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Field.cpp @@ -0,0 +1,374 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +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::CN( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + d[ ii ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +void Field::ICP( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = ist; i <= ied; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + int ii = i - 1; + d[ ii ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +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 ]; + this->u[ ighost ] = - 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 ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + //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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Field.h new file mode 100644 index 00000000..ead80648 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Field.h @@ -0,0 +1,42 @@ +#pragma once +#include + +class Zone; +class Grid; +class Region; + +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 CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Global.cpp new file mode 100644 index 00000000..d5de70d5 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Global.cpp @@ -0,0 +1,298 @@ +#include "Global.h" +#include "Grid.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; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Global.h new file mode 100644 index 00000000..f1e20431 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Global.h @@ -0,0 +1,110 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "Grid.h" + +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 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Grid.cpp new file mode 100644 index 00000000..16d3e30d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Grid.cpp @@ -0,0 +1,273 @@ +#include "Grid.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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Grid.h new file mode 100644 index 00000000..8d84f595 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Grid.h @@ -0,0 +1,100 @@ +#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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Post.cpp new file mode 100644 index 00000000..548fff2d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Post.cpp @@ -0,0 +1,286 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include +#include +#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 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Solver.cpp new file mode 100644 index 00000000..3bfb9a3b --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Solver.cpp @@ -0,0 +1,473 @@ +#include "Solver.h" +#include "Parallel.h" +#include "Post.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + this->scheme = Scheme::ICP; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + 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::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( 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"; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Solver.h new file mode 100644 index 00000000..ca8a8a42 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + 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 CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Weno.cpp new file mode 100644 index 00000000..9b79a0e2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Weno.cpp @@ -0,0 +1,277 @@ +#include "Weno.h" + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 3 ] = 4.0 * u[ i ] - 3.0 * u[ i + 1 ]; + + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + u[ i + 3 ] = 4.0 * u[ i ] - 3.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, vec1d & u, vec1d & res ) +{ + vec1d uL; + uL.Allocate( 0, N, 0 ); + + vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, ut, res, dx, dt ); + runge_kutta_stage2( N, un, ut, res, dx, dt ); + runge_kutta_stage3( N, un, ut, res, dx, dt ); +} + +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, un, res ); + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, un ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector u( ns + 1 ); + + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + u[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, ut, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + u[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Weno.h new file mode 100644 index 00000000..747eb983 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/Weno.h @@ -0,0 +1,64 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, vec1d & u, vec1d & f ); +void wenoR( int N, vec1d & u, vec1d & f ); +void rhs( int N, double dx, vec1d & u, vec1d & r ); +void boundary( int N, vec1d & u ); + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); + +void numerical(); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/CMakeLists.txt new file mode 100644 index 00000000..f4e3e147 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/Solver.cpp new file mode 100644 index 00000000..9e6b758b --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/Solver.cpp @@ -0,0 +1,294 @@ +#include "Solver.h" + +Solver::Solver() +{ + ; +} + +Solver::~Solver() +{ + ; +} + +void Solver::Solve() +{ + numerical(); +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 3 ] = 4.0 * u[ i ] - 3.0 * u[ i + 1 ]; + + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + u[ i + 3 ] = 4.0 * u[ i ] - 3.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, vec1d & u, vec1d & res ) +{ + vec1d uL; + uL.Allocate( 0, N, 0 ); + + vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, ut, res, dx, dt ); + runge_kutta_stage2( N, un, ut, res, dx, dt ); + runge_kutta_stage3( N, un, ut, res, dx, dt ); + un = ut; +} + +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, ut ); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + ut = un; + ulist[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, ut, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + ulist[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, ulist ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/Solver.h new file mode 100644 index 00000000..af6cdfe8 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/Solver.h @@ -0,0 +1,72 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, vec1d & u, vec1d & f ); +void wenoR( int N, vec1d & u, vec1d & f ); +void rhs( int N, double dx, vec1d & u, vec1d & r ); +void boundary( int N, vec1d & u ); +void numerical(); + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + void Solve(); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/main.cpp new file mode 100644 index 00000000..6c4dab24 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/main.cpp @@ -0,0 +1,8 @@ +#include "Solver.h" + +int main( int argc, char ** argv ) +{ + Solver solver; + solver.Solve(); + return 0; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02a0/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/CMakeLists.txt new file mode 100644 index 00000000..b91d6f42 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/CMakeLists.txt @@ -0,0 +1,84 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/CgnsUtil.cpp new file mode 100644 index 00000000..c582c75c --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/CgnsUtil.cpp @@ -0,0 +1,583 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Field.cpp new file mode 100644 index 00000000..10142909 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Field.cpp @@ -0,0 +1,374 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +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::CN( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + d[ ii ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +void Field::ICP( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = ist; i <= ied; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + int ii = i - 1; + d[ ii ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +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 ]; + this->u[ ighost ] = - 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 ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + //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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Field.h new file mode 100644 index 00000000..ead80648 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Field.h @@ -0,0 +1,42 @@ +#pragma once +#include + +class Zone; +class Grid; +class Region; + +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 CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Global.cpp new file mode 100644 index 00000000..d5de70d5 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Global.cpp @@ -0,0 +1,298 @@ +#include "Global.h" +#include "Grid.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; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Global.h new file mode 100644 index 00000000..f1e20431 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Global.h @@ -0,0 +1,110 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "Grid.h" + +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 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Grid.cpp new file mode 100644 index 00000000..16d3e30d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Grid.cpp @@ -0,0 +1,273 @@ +#include "Grid.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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Grid.h new file mode 100644 index 00000000..8d84f595 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Grid.h @@ -0,0 +1,100 @@ +#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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Post.cpp new file mode 100644 index 00000000..548fff2d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Post.cpp @@ -0,0 +1,286 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include +#include +#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 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Solver.cpp new file mode 100644 index 00000000..2eb78001 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Solver.cpp @@ -0,0 +1,473 @@ +#include "Solver.h" +#include "Parallel.h" +#include "Post.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + this->scheme = Scheme::ICP; + //this->scheme = Scheme::WENO; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + 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::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( 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"; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Solver.h new file mode 100644 index 00000000..ca8a8a42 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + 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 CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Weno.cpp new file mode 100644 index 00000000..9b79a0e2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Weno.cpp @@ -0,0 +1,277 @@ +#include "Weno.h" + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 3 ] = 4.0 * u[ i ] - 3.0 * u[ i + 1 ]; + + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + u[ i + 3 ] = 4.0 * u[ i ] - 3.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, vec1d & u, vec1d & res ) +{ + vec1d uL; + uL.Allocate( 0, N, 0 ); + + vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, ut, res, dx, dt ); + runge_kutta_stage2( N, un, ut, res, dx, dt ); + runge_kutta_stage3( N, un, ut, res, dx, dt ); +} + +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, un, res ); + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + un[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, un ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector u( ns + 1 ); + + for ( int i = 0; i < u.size(); ++ i ) + { + u[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + u[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, ut, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + u[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, u ); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Weno.h new file mode 100644 index 00000000..747eb983 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/Weno.h @@ -0,0 +1,64 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, vec1d & u, vec1d & f ); +void wenoR( int N, vec1d & u, vec1d & f ); +void rhs( int N, double dx, vec1d & u, vec1d & r ); +void boundary( int N, vec1d & u ); + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); + +void numerical(); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/CMakeLists.txt new file mode 100644 index 00000000..b91d6f42 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/CMakeLists.txt @@ -0,0 +1,84 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/CgnsUtil.cpp new file mode 100644 index 00000000..c582c75c --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/CgnsUtil.cpp @@ -0,0 +1,583 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Field.cpp new file mode 100644 index 00000000..22f0fc8d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Field.cpp @@ -0,0 +1,347 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +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::FTCS( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->u, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = u[ i ] + dt * r[ i ]; + } +} + +void Field::CN( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + d[ ii ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +void Field::ICP( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = ist; i <= ied; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + int ii = i - 1; + d[ ii ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +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::UpdateOldField() +{ + for ( int i = 0; i < this->u.size(); ++ i ) + { + this->un[ i ] = this->u[ i ]; + } +} + +void Field::RungeKutta3Stage0( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->u, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = u[ i ] + dt * r[ i ]; + } +} + +void Field::RungeKutta3Stage1( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->u, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ 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 ]; + this->u[ ighost ] = - 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 ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} + + +void Field::PostProcess( Grid * grid ) +{ + //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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Field.h new file mode 100644 index 00000000..85879522 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Field.h @@ -0,0 +1,41 @@ +#pragma once +#include + +class Zone; +class Grid; +class Region; + +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 ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + 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(); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Global.cpp new file mode 100644 index 00000000..d5de70d5 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Global.cpp @@ -0,0 +1,298 @@ +#include "Global.h" +#include "Grid.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; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Global.h new file mode 100644 index 00000000..f1e20431 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Global.h @@ -0,0 +1,110 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "Grid.h" + +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 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Grid.cpp new file mode 100644 index 00000000..16d3e30d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Grid.cpp @@ -0,0 +1,273 @@ +#include "Grid.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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Grid.h new file mode 100644 index 00000000..8d84f595 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Grid.h @@ -0,0 +1,100 @@ +#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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Post.cpp new file mode 100644 index 00000000..548fff2d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Post.cpp @@ -0,0 +1,286 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include +#include +#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 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Solver.cpp new file mode 100644 index 00000000..63316940 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Solver.cpp @@ -0,0 +1,464 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + this->scheme = Scheme::ICP; + //this->scheme = Scheme::WENO; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../burgers1d1blocksv1.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::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::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"; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Solver.h new file mode 100644 index 00000000..8ee1063f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Solver.h @@ -0,0 +1,48 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + 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 UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Weno.cpp new file mode 100644 index 00000000..26c56f9e --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Weno.cpp @@ -0,0 +1,279 @@ +#include "Weno.h" + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, vec1d & u, vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 3 ] = 4.0 * u[ i ] - 3.0 * u[ i + 1 ]; + + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + u[ i + 3 ] = 4.0 * u[ i ] - 3.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, vec1d & u, vec1d & res ) +{ + vec1d uL; + uL.Allocate( 0, N, 0 ); + + vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, ut, res, dx, dt ); + runge_kutta_stage2( N, un, ut, res, dx, dt ); + runge_kutta_stage3( N, un, ut, res, dx, dt ); + un = ut; +} + +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, ut ); +} + +void DumpCsvFile( const std::string &filename, vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + ut = un; + ulist[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, ut, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + ulist[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, ulist ); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Weno.h new file mode 100644 index 00000000..747eb983 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/Weno.h @@ -0,0 +1,64 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +class vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + vec1d & operator = ( const vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; + + +void DumpCsvFile( const std::string & filename, vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, vec1d & u, vec1d & f ); +void wenoR( int N, vec1d & u, vec1d & f ); +void rhs( int N, double dx, vec1d & u, vec1d & r ); +void boundary( int N, vec1d & u ); + +void runge_kutta( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, vec1d & un, vec1d & ut, vec1d & res, double dx, double dt ); + +void numerical(); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/burgers1d1blocksv1.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/burgers1d1blocksv1.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/heat1d1block.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/heat1d1block.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02c/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/CMakeLists.txt new file mode 100644 index 00000000..4892adaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/CgnsUtil.cpp new file mode 100644 index 00000000..255ae2bd --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Field.cpp new file mode 100644 index 00000000..76647dcc --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Field.cpp @@ -0,0 +1,335 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +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; + + int N = this->ni; + + u_e.resize( ni_total ); + u.Allocate( 0, ni_total - 1 ); + un.Allocate( 0, ni_total - 1 ); + r.Allocate( 0, ni_total - 1 ); + + // 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->u, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = u[ i ] + dt * r[ i ]; + } +} + +void Field::CN( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + d[ ii ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +void Field::ICP( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = ist; i <= ied; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + int ii = i - 1; + d[ ii ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = ist; i <= ied; ++ i ) + { + int ii = i - 1; + u[ i ] = values[ ii ]; + } +} + +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::UpdateOldField() +{ + this->un = this->u; +} + +void Field::RungeKutta3Stage0( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->u, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = u[ i ] + dt * r[ i ]; + } +} + +void Field::RungeKutta3Stage1( Zone * zone ) +{ + int ist = 1; + int ied = ni; + + this->Rhs( this->u, this->r ); + + for ( int i = ist; i <= ied; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ 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( Vec1d & u, Vec1d & 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 ]; + this->u[ ighost ] = - 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 ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Field.h new file mode 100644 index 00000000..889e3ec4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Field.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + std::vector u_e; + Vec1d u, un; + Vec1d r; +public: + int ni; + int nt; + double dx, dt, t; + double alpha, beta; +public: + void Init( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Global.cpp new file mode 100644 index 00000000..d5de70d5 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Global.cpp @@ -0,0 +1,298 @@ +#include "Global.h" +#include "Grid.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; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Global.h new file mode 100644 index 00000000..dc69d44c --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Global.h @@ -0,0 +1,110 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +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 Zone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Grid.cpp new file mode 100644 index 00000000..16d3e30d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Grid.cpp @@ -0,0 +1,273 @@ +#include "Grid.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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Grid.h new file mode 100644 index 00000000..8d84f595 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Grid.h @@ -0,0 +1,100 @@ +#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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Post.cpp new file mode 100644 index 00000000..548fff2d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Post.cpp @@ -0,0 +1,286 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include +#include +#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 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Solver.cpp new file mode 100644 index 00000000..d9f52e01 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Solver.cpp @@ -0,0 +1,465 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + this->scheme = Scheme::ICP; + //this->scheme = Scheme::WENO; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + //std::string fileName = "../burgers1d1blocksv1.cgns"; + 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::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::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"; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Solver.h new file mode 100644 index 00000000..8ee1063f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Solver.h @@ -0,0 +1,48 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + 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 UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Weno.cpp new file mode 100644 index 00000000..a63ec24b --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Weno.cpp @@ -0,0 +1,283 @@ +#include "Weno.h" +#include +#include +#include +#include + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, Vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 3 ] = 4.0 * u[ i ] - 3.0 * u[ i + 1 ]; + + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + u[ i + 3 ] = 4.0 * u[ i ] - 3.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, N, 0 ); + + Vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, Vec1d & un, Vec1d & ut, Vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, ut, res, dx, dt ); + runge_kutta_stage2( N, un, ut, res, dx, dt ); + runge_kutta_stage3( N, un, ut, res, dx, dt ); + un = ut; +} + +void runge_kutta_stage1( int N, Vec1d & un, Vec1d & ut, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage2( int N, Vec1d & un, Vec1d & ut, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = 0.75 * un[ i ] + 0.25 * ut[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, ut ); +} + +void runge_kutta_stage3( int N, Vec1d & un, Vec1d & ut, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, ut, res ); + + for ( int i = 0; i < N; ++ i ) + { + ut[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * ut[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, ut ); +} + +void DumpCsvFile( const std::string &filename, Vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + Vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + Vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + Vec1d ut; + ut.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + Vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + ut = un; + ulist[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, ut, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + ulist[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, ulist ); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Weno.h new file mode 100644 index 00000000..307b582d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/Weno.h @@ -0,0 +1,23 @@ +#pragma once +#include "Vec1d.h" +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +void DumpCsvFile( const std::string & filename, Vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); +void rhs( int N, double dx, Vec1d & u, Vec1d & r ); +void boundary( int N, Vec1d & u ); + +void runge_kutta( int N, Vec1d & un, Vec1d & ut, Vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, Vec1d & un, Vec1d & ut, Vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, Vec1d & un, Vec1d & ut, Vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, Vec1d & un, Vec1d & ut, Vec1d & res, double dx, double dt ); + +void numerical(); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/burgers1d1blocksv1.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/burgers1d1blocksv1.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/heat1d1block.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/heat1d1block.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02d/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/CMakeLists.txt new file mode 100644 index 00000000..4892adaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/CgnsUtil.cpp new file mode 100644 index 00000000..255ae2bd --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Field.cpp new file mode 100644 index 00000000..487a0d8f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Field.cpp @@ -0,0 +1,319 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void Field::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void Field::InitHeatEquation( 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->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + //u_e.Allocate( 0, ni_total - 1 ); + //u.Allocate( 0, ni_total - 1 ); + //un.Allocate( 0, ni_total - 1 ); + //res.Allocate( 0, ni_total - 1 ); + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void Field::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void Field::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ 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::UpdateOldField() +{ + this->un = this->u; +} + +void Field::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void Field::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void Field::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + + +void Field::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ 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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - 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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Field.h new file mode 100644 index 00000000..85cc346c --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Field.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Global.cpp new file mode 100644 index 00000000..d5de70d5 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Global.cpp @@ -0,0 +1,298 @@ +#include "Global.h" +#include "Grid.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; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Global.h new file mode 100644 index 00000000..dc69d44c --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Global.h @@ -0,0 +1,110 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +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 Zone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Grid.cpp new file mode 100644 index 00000000..16d3e30d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Grid.cpp @@ -0,0 +1,273 @@ +#include "Grid.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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Grid.h new file mode 100644 index 00000000..8d84f595 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Grid.h @@ -0,0 +1,100 @@ +#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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Post.cpp new file mode 100644 index 00000000..537f8bad --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Post.cpp @@ -0,0 +1,283 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Solver.cpp new file mode 100644 index 00000000..d383cb12 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Solver.cpp @@ -0,0 +1,465 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + this->scheme = Scheme::ICP; + //this->scheme = Scheme::WENO; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + //std::string fileName = "../burgers1d1blocksv1.cgns"; + 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::SolveFields() +{ + for ( int it = 0; it < Global::nt; ++ it ) + { + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::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"; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Solver.h new file mode 100644 index 00000000..8ee1063f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Solver.h @@ -0,0 +1,48 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + 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 UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Weno.cpp new file mode 100644 index 00000000..065f3ad9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Weno.cpp @@ -0,0 +1,283 @@ +#include "Weno.h" +#include +#include +#include +#include + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, Vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 3 ] = 4.0 * u[ i ] - 3.0 * u[ i + 1 ]; + + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + u[ i + 3 ] = 4.0 * u[ i ] - 3.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, N, 0 ); + + Vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, u, res, dx, dt ); + runge_kutta_stage2( N, un, u, res, dx, dt ); + runge_kutta_stage3( N, un, u, res, dx, dt ); + un = u; +} + +void runge_kutta_stage1( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, u, res ); + for ( int i = 0; i < N; ++ i ) + { + u[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, u ); +} + +void runge_kutta_stage2( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, u, res ); + + for ( int i = 0; i < N; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, u ); +} + +void runge_kutta_stage3( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, u, res ); + + for ( int i = 0; i < N; ++ i ) + { + u[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * u[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, u ); +} + +void DumpCsvFile( const std::string &filename, Vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + Vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + Vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + Vec1d u; + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + Vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + u = un; + ulist[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, u, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + ulist[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, ulist ); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Weno.h new file mode 100644 index 00000000..4e98984b --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/Weno.h @@ -0,0 +1,23 @@ +#pragma once +#include "Vec1d.h" +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +void DumpCsvFile( const std::string & filename, Vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); +void rhs( int N, double dx, Vec1d & u, Vec1d & r ); +void boundary( int N, Vec1d & u ); + +void runge_kutta( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); + +void numerical(); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/burgers1d1blocksv1.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/burgers1d1blocksv1.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/heat1d1block.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/heat1d1block.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02e/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/CMakeLists.txt new file mode 100644 index 00000000..4892adaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/CgnsUtil.cpp new file mode 100644 index 00000000..255ae2bd --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Field.cpp new file mode 100644 index 00000000..293ab296 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Field.cpp @@ -0,0 +1,314 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( 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->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::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 FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Field.h new file mode 100644 index 00000000..5693c64a --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Field.h @@ -0,0 +1,56 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Global.cpp new file mode 100644 index 00000000..d5de70d5 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Global.cpp @@ -0,0 +1,298 @@ +#include "Global.h" +#include "Grid.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; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Global.h new file mode 100644 index 00000000..dc69d44c --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Global.h @@ -0,0 +1,110 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +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 Zone; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Grid.cpp new file mode 100644 index 00000000..16d3e30d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Grid.cpp @@ -0,0 +1,273 @@ +#include "Grid.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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Grid.h new file mode 100644 index 00000000..8d84f595 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Grid.h @@ -0,0 +1,100 @@ +#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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Post.cpp new file mode 100644 index 00000000..537f8bad --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Post.cpp @@ -0,0 +1,283 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Solver.cpp new file mode 100644 index 00000000..ff3e3f2b --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Solver.cpp @@ -0,0 +1,465 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + this->scheme = Scheme::ICP; + //this->scheme = Scheme::WENO; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + this->PostProcess(); +} + +void Solver::ReadGrid() +{ + //std::string fileName = "../burgers1d1blocksv1.cgns"; + 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 FieldSub(); + 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::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + 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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::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"; +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Solver.h new file mode 100644 index 00000000..8ee1063f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Solver.h @@ -0,0 +1,48 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + 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 UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Weno.cpp new file mode 100644 index 00000000..065f3ad9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Weno.cpp @@ -0,0 +1,283 @@ +#include "Weno.h" +#include +#include +#include +#include + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, Vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 3 ] = 4.0 * u[ i ] - 3.0 * u[ i + 1 ]; + + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + u[ i + 3 ] = 4.0 * u[ i ] - 3.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, N, 0 ); + + Vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, u, res, dx, dt ); + runge_kutta_stage2( N, un, u, res, dx, dt ); + runge_kutta_stage3( N, un, u, res, dx, dt ); + un = u; +} + +void runge_kutta_stage1( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, u, res ); + for ( int i = 0; i < N; ++ i ) + { + u[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, u ); +} + +void runge_kutta_stage2( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, u, res ); + + for ( int i = 0; i < N; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, u ); +} + +void runge_kutta_stage3( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, u, res ); + + for ( int i = 0; i < N; ++ i ) + { + u[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * u[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, u ); +} + +void DumpCsvFile( const std::string &filename, Vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + double ds = tm / ns; + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + Vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + Vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + Vec1d u; + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + Vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + u = un; + ulist[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, u, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + ulist[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, ulist ); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Weno.h new file mode 100644 index 00000000..4e98984b --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/Weno.h @@ -0,0 +1,23 @@ +#pragma once +#include "Vec1d.h" +#include + +template +auto SQR(Args... args) { + return (... + (args * args)); +} + +void DumpCsvFile( const std::string & filename, Vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); +void rhs( int N, double dx, Vec1d & u, Vec1d & r ); +void boundary( int N, Vec1d & u ); + +void runge_kutta( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); + +void numerical(); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/burgers1d1blocksv1.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/burgers1d1blocksv1.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/heat1d1block.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/heat1d1block.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02f/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/CMakeLists.txt new file mode 100644 index 00000000..4892adaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/CgnsUtil.cpp new file mode 100644 index 00000000..3bcbd100 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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.Allocate( 0, nNodes - 1 ); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Field.cpp new file mode 100644 index 00000000..bf47a1e7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Field.cpp @@ -0,0 +1,311 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Field.h new file mode 100644 index 00000000..d0479a13 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Field.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} + virtual void PostProcess( Grid * grid ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Global.cpp new file mode 100644 index 00000000..ef66fa06 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Global.cpp @@ -0,0 +1,299 @@ +#include "Global.h" +#include "Grid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::iter = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Global.h new file mode 100644 index 00000000..5d4fe986 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Global.h @@ -0,0 +1,106 @@ +#pragma once +#include "Vec1d.h" +#include +#include +#include +#include +#include +#include + +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 Zone; +class Grid; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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 iter; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Grid.cpp new file mode 100644 index 00000000..993ea5f9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Grid.cpp @@ -0,0 +1,274 @@ +#include "Grid.h" +#include "Vec1d.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( Vec1d &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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Grid.h new file mode 100644 index 00000000..b92a53ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Grid.h @@ -0,0 +1,110 @@ +#pragma once +#include "Vec1d.h" +#include +#include + +class Vec1d; + +class Grid +{ +public: + int zoneIndex; + Vec1d x; +}; + +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( Vec1d & 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/MyWenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/MyWenoPlot.py new file mode 100644 index 00000000..74dc3297 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/MyWenoPlot.py @@ -0,0 +1,46 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final0.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount +print("ni=",ni) + +ns = 10 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +for j in range(ns+1): + filename = 'field_final'+str((j)*250)+'.csv' + print('filename=',filename) + with open(filename, newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + x[i] = float(row[0]) + u[i][j] = float(row[1]) + i += 1 + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") +#exit() +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Post.cpp new file mode 100644 index 00000000..ef482e1f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Post.cpp @@ -0,0 +1,284 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include "Grid.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Solver.cpp new file mode 100644 index 00000000..25b8f23d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Solver.cpp @@ -0,0 +1,496 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "Weno.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + //this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../burgers1d1blocksv1.cgns"; + //std::string fileName = "../heat1d1block.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +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 = nullptr; + if ( scheme == Scheme::WENO ) { + field = new WenoField(); + } + else { + field = new FieldSub(); + } + 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::DumpInitialFields() +{ + this->PostProcess(); +} + +void Solver::SolveFields() +{ + this->DumpInitialFields(); + for ( int it = 0; it < Global::nt; ++ it ) + { + Global::iter = it; + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO: + this->RungeKutta(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + if ( ( Global::iter + 1 ) % 250 == 0 ) + { + std::print( "it = {} nt = {}\n", Global::iter + 1, Global::nt ); + this->PostProcess(); + } + + } +} + +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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::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(); + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->PostProcess( grid ); + } +} + +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 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; +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Solver.h new file mode 100644 index 00000000..390feb3d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); + void DumpInitialFields(); +public: + void Boundary(); + void UpdateOldField(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Weno.cpp new file mode 100644 index 00000000..82d39b3c --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Weno.cpp @@ -0,0 +1,516 @@ +#include "Weno.h" +#include "Global.h" +#include "Grid.h" +#include "cgnslib.h" +#include +#include +#include +#include +#include + +void WenoField::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = 0.0001; + this->total_time = 0.25; + this->nt = std::round( total_time / dt ); + this->ns = 10; + + std::print( "ni={}\n",ni ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "total_time={}\n", total_time ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\n"; + + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + Global::nt = nt; + + int ighost = 3; + int ist = 0 - ighost; + int ied = this->ni - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + res.Allocate( 0, this->ni, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + int kkk = 1; +} + +void WenoField::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void WenoField::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 WenoField::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void WenoField::Rhs( Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, ni, 0 ); + + Vec1d uR; + uR.Allocate( 0, ni, 0 ); + + wenoL( ni, u, uL ); + wenoR( ni, u, uR ); + + for ( int i = 0; i < ni; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void WenoField::UpdateOldField() +{ + this->un = this->u; +} + +void WenoField::PostProcess( Grid * grid ) +{ + std::string csvname = std::format( "field_final{}.csv", Global::iter+1 ); + this->DumpField( csvname, grid->x, u ); +} + +void WenoField::DumpField( const std::string & filename, Vec1d & x, Vec1d & u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} {:.16f}", x[ i ], u[ i ] ); + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + +void boundary( int N, Vec1d & u ) +{ + //left bc + int i = 0; + u[ i ] = 0.0; + u[ i - 1 ] = 2.0 * u[ i ] - u[ i + 1 ]; + u[ i - 2 ] = 3.0 * u[ i ] - 2.0 * u[ i + 1 ]; + u[ i - 3 ] = 4.0 * u[ i ] - 3.0 * u[ i + 1 ]; + + //right bc + i = N - 1; + u[ i ] = 0.0; + u[ i + 1 ] = 2.0 * u[ i ] - u[ i - 1 ]; + u[ i + 2 ] = 3.0 * u[ i ] - 2.0 * u[ i - 1 ]; + u[ i + 3 ] = 4.0 * u[ i ] - 3.0 * u[ i - 1 ]; +} + +//----------------------------------------------------------------------------- +// Calculate right hand term of the inviscid Burgers equation +//----------------------------------------------------------------------------- +void rhs( int N, double dx, Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, N, 0 ); + + Vec1d uR; + uR.Allocate( 0, N, 0 ); + + wenoL( N, u, uL ); + wenoR( N, u, uR ); + + for ( int i = 0; i < N; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void runge_kutta( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + runge_kutta_stage1( N, un, u, res, dx, dt ); + runge_kutta_stage2( N, un, u, res, dx, dt ); + runge_kutta_stage3( N, un, u, res, dx, dt ); + un = u; +} + +void runge_kutta_stage1( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, u, res ); + for ( int i = 0; i < N; ++ i ) + { + u[ i ] = un[ i ] + dt * res[ i ]; + } + boundary( N, u ); +} + +void runge_kutta_stage2( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, u, res ); + + for ( int i = 0; i < N; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } + boundary( N, u ); +} + +void runge_kutta_stage3( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ) +{ + rhs( N, dx, u, res ); + + for ( int i = 0; i < N; ++ i ) + { + u[ i ] = ( 1.0 / 3.0 ) * un[ i ] + ( 2.0 / 3.0 ) * u[ i ] + ( 2.0 / 3.0 ) * dt * res[ i ]; + } + boundary( N, u ); +} + +void DumpCsvFile( const std::string &filename, Vec1d &x, std::vector &u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} ", x[ i ] ); + int nj = u.size(); + for ( int j = 0; j < nj; ++ j ) + { + double value = u[ j ][ i ]; + str += std::format( "{:.16f}", value ); + if ( j != nj - 1 ) + { + str += " "; + } + } + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +//----------------------------------------------------------------------------- +// Compute numerical solution +// - Time integration using Runge-Kutta third order +// - 5th-order Compact WENO scheme for spatial terms +//----------------------------------------------------------------------------- +void numerical() +{ + int N = 201; + int ns = 10; + double dt = 0.0001; + double tm = 0.25; + + double dx = 1.0 / ( N - 1 ); + int nt = std::round( tm / dt ); + + std::print( "Npoints={}\n", N ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "tm={}\n", tm ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + + Vec1d x; + x.Allocate( 0, N - 1, 0 ); // npoints = N = nx + 1 + + int ighost = 3; + int ist = 0 - ighost; + int ied = N - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + Vec1d un; + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + + Vec1d u; + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + + Vec1d res; + res.Allocate( 0, N, 0 ); //N+1 + + int k = 0; // record index + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = dx * ( i ); + un[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + boundary( N, un ); + u = un; + ulist[ k ] = un; //store solution at t = 0; + + for ( int it = 1; it <= nt; ++ it ) + { + runge_kutta( N, un, u, res, dx, dt ); + + if ( it % freq == 0 ) + { + k += 1; + ulist[ k ] = un; + std::print( "k={}, ns={}\n", k, ns ); + } + } + + DumpCsvFile( "field_final.csv", x, ulist ); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Weno.h new file mode 100644 index 00000000..e5f34f6d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/Weno.h @@ -0,0 +1,50 @@ +#pragma once +#include "Vec1d.h" +#include "Field.h" +#include + +template +auto SQR(Args... args) { + return ( ... + ( args * args ) ); +} + +class WenoField : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + int ns; +public: + void Init( Grid * grid ); +public: + void PhysicalBoundary( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); + void Rhs( Vec1d & u, Vec1d & res ); +public: + void UpdateOldField(); + void PostProcess( Grid * grid ); + void DumpField( const std::string & filename, Vec1d & x, Vec1d & u ); +}; + +void DumpCsvFile( const std::string & filename, Vec1d & x, std::vector & u ); +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); +void rhs( int N, double dx, Vec1d & u, Vec1d & r ); +void boundary( int N, Vec1d & u ); + +void runge_kutta( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); +void runge_kutta_stage1( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); +void runge_kutta_stage2( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); +void runge_kutta_stage3( int N, Vec1d & un, Vec1d & u, Vec1d & res, double dx, double dt ); + +void numerical(); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/burgers1d1blocksv1.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/burgers1d1blocksv1.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/heat1d1block.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/heat1d1block.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02g/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/CMakeLists.txt new file mode 100644 index 00000000..4892adaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/CgnsUtil.cpp new file mode 100644 index 00000000..3bcbd100 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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.Allocate( 0, nNodes - 1 ); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Field.cpp new file mode 100644 index 00000000..bf47a1e7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Field.cpp @@ -0,0 +1,311 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Field.h new file mode 100644 index 00000000..d0479a13 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Field.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} + virtual void PostProcess( Grid * grid ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Global.cpp new file mode 100644 index 00000000..ef66fa06 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Global.cpp @@ -0,0 +1,299 @@ +#include "Global.h" +#include "Grid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::iter = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Global.h new file mode 100644 index 00000000..5d4fe986 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Global.h @@ -0,0 +1,106 @@ +#pragma once +#include "Vec1d.h" +#include +#include +#include +#include +#include +#include + +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 Zone; +class Grid; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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 iter; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Grid.cpp new file mode 100644 index 00000000..993ea5f9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Grid.cpp @@ -0,0 +1,274 @@ +#include "Grid.h" +#include "Vec1d.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( Vec1d &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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Grid.h new file mode 100644 index 00000000..b92a53ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Grid.h @@ -0,0 +1,110 @@ +#pragma once +#include "Vec1d.h" +#include +#include + +class Vec1d; + +class Grid +{ +public: + int zoneIndex; + Vec1d x; +}; + +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( Vec1d & 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/MyWenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/MyWenoPlot.py new file mode 100644 index 00000000..74dc3297 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/MyWenoPlot.py @@ -0,0 +1,46 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final0.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount +print("ni=",ni) + +ns = 10 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +for j in range(ns+1): + filename = 'field_final'+str((j)*250)+'.csv' + print('filename=',filename) + with open(filename, newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + x[i] = float(row[0]) + u[i][j] = float(row[1]) + i += 1 + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") +#exit() +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Post.cpp new file mode 100644 index 00000000..ef482e1f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Post.cpp @@ -0,0 +1,284 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include "Grid.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Solver.cpp new file mode 100644 index 00000000..25b8f23d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Solver.cpp @@ -0,0 +1,496 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "Weno.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + //this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../burgers1d1blocksv1.cgns"; + //std::string fileName = "../heat1d1block.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +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 = nullptr; + if ( scheme == Scheme::WENO ) { + field = new WenoField(); + } + else { + field = new FieldSub(); + } + 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::DumpInitialFields() +{ + this->PostProcess(); +} + +void Solver::SolveFields() +{ + this->DumpInitialFields(); + for ( int it = 0; it < Global::nt; ++ it ) + { + Global::iter = it; + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO: + this->RungeKutta(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + if ( ( Global::iter + 1 ) % 250 == 0 ) + { + std::print( "it = {} nt = {}\n", Global::iter + 1, Global::nt ); + this->PostProcess(); + } + + } +} + +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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::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(); + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->PostProcess( grid ); + } +} + +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 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; +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Solver.h new file mode 100644 index 00000000..390feb3d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); + void DumpInitialFields(); +public: + void Boundary(); + void UpdateOldField(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Weno.cpp new file mode 100644 index 00000000..7aa01855 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Weno.cpp @@ -0,0 +1,338 @@ +#include "Weno.h" +#include "Global.h" +#include "Grid.h" +#include "cgnslib.h" +#include +#include +#include +#include +#include + +void WenoField::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = 0.0001; + this->total_time = 0.25; + this->nt = std::round( total_time / dt ); + this->ns = 10; + + std::print( "ni={}\n",ni ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "total_time={}\n", total_time ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\n"; + + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + Global::nt = nt; + + int ighost = 3; + int ist = 0 - ighost; + int ied = this->ni - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + res.Allocate( 0, this->ni, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + int kkk = 1; +} + +void WenoField::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void WenoField::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 WenoField::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void WenoField::Rhs( Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, ni, 0 ); + + Vec1d uR; + uR.Allocate( 0, ni, 0 ); + + wenoL( ni, u, uL ); + wenoR( ni, u, uR ); + + for ( int i = 0; i < ni; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void WenoField::UpdateOldField() +{ + this->un = this->u; +} + +void WenoField::PostProcess( Grid * grid ) +{ + std::string csvname = std::format( "field_final{}.csv", Global::iter+1 ); + this->DumpField( csvname, grid->x, u ); +} + +void WenoField::DumpField( const std::string & filename, Vec1d & x, Vec1d & u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} {:.16f}", x[ i ], u[ i ] ); + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + + + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Weno.h new file mode 100644 index 00000000..afd57efe --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/Weno.h @@ -0,0 +1,40 @@ +#pragma once +#include "Vec1d.h" +#include "Field.h" +#include + +template +auto SQR(Args... args) { + return ( ... + ( args * args ) ); +} + +class WenoField : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + int ns; +public: + void Init( Grid * grid ); +public: + void PhysicalBoundary( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); + void Rhs( Vec1d & u, Vec1d & res ); +public: + void UpdateOldField(); + void PostProcess( Grid * grid ); + void DumpField( const std::string & filename, Vec1d & x, Vec1d & u ); +}; + +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/burgers1d1blocksv1.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/burgers1d1blocksv1.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/heat1d1block.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/heat1d1block.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02h/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/CMakeLists.txt new file mode 100644 index 00000000..4892adaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/CgnsUtil.cpp new file mode 100644 index 00000000..3bcbd100 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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.Allocate( 0, nNodes - 1 ); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Field.cpp new file mode 100644 index 00000000..bf47a1e7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Field.cpp @@ -0,0 +1,311 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Field.h new file mode 100644 index 00000000..d0479a13 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Field.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} + virtual void PostProcess( Grid * grid ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Global.cpp new file mode 100644 index 00000000..ef66fa06 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Global.cpp @@ -0,0 +1,299 @@ +#include "Global.h" +#include "Grid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::iter = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; + +std::vector Global::zones; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Global.h new file mode 100644 index 00000000..5d4fe986 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Global.h @@ -0,0 +1,106 @@ +#pragma once +#include "Vec1d.h" +#include +#include +#include +#include +#include +#include + +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 Zone; +class Grid; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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 iter; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Grid.cpp new file mode 100644 index 00000000..993ea5f9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Grid.cpp @@ -0,0 +1,274 @@ +#include "Grid.h" +#include "Vec1d.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( Vec1d &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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Grid.h new file mode 100644 index 00000000..b92a53ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Grid.h @@ -0,0 +1,110 @@ +#pragma once +#include "Vec1d.h" +#include +#include + +class Vec1d; + +class Grid +{ +public: + int zoneIndex; + Vec1d x; +}; + +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( Vec1d & 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/MyWenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/MyWenoPlot.py new file mode 100644 index 00000000..74dc3297 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/MyWenoPlot.py @@ -0,0 +1,46 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final0.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount +print("ni=",ni) + +ns = 10 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +for j in range(ns+1): + filename = 'field_final'+str((j)*250)+'.csv' + print('filename=',filename) + with open(filename, newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + x[i] = float(row[0]) + u[i][j] = float(row[1]) + i += 1 + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") +#exit() +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Post.cpp new file mode 100644 index 00000000..ef482e1f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Post.cpp @@ -0,0 +1,284 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include "Grid.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Solver.cpp new file mode 100644 index 00000000..25b8f23d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Solver.cpp @@ -0,0 +1,496 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "Weno.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + //this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../burgers1d1blocksv1.cgns"; + //std::string fileName = "../heat1d1block.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +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 = nullptr; + if ( scheme == Scheme::WENO ) { + field = new WenoField(); + } + else { + field = new FieldSub(); + } + 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::DumpInitialFields() +{ + this->PostProcess(); +} + +void Solver::SolveFields() +{ + this->DumpInitialFields(); + for ( int it = 0; it < Global::nt; ++ it ) + { + Global::iter = it; + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO: + this->RungeKutta(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + if ( ( Global::iter + 1 ) % 250 == 0 ) + { + std::print( "it = {} nt = {}\n", Global::iter + 1, Global::nt ); + this->PostProcess(); + } + + } +} + +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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::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(); + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->PostProcess( grid ); + } +} + +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 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; +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Solver.h new file mode 100644 index 00000000..390feb3d --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Solver.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); + void DumpInitialFields(); +public: + void Boundary(); + void UpdateOldField(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Weno.cpp new file mode 100644 index 00000000..7aa01855 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Weno.cpp @@ -0,0 +1,338 @@ +#include "Weno.h" +#include "Global.h" +#include "Grid.h" +#include "cgnslib.h" +#include +#include +#include +#include +#include + +void WenoField::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = 0.0001; + this->total_time = 0.25; + this->nt = std::round( total_time / dt ); + this->ns = 10; + + std::print( "ni={}\n",ni ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "total_time={}\n", total_time ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\n"; + + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + Global::nt = nt; + + int ighost = 3; + int ist = 0 - ighost; + int ied = this->ni - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + res.Allocate( 0, this->ni, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + int kkk = 1; +} + +void WenoField::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void WenoField::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 WenoField::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void WenoField::Rhs( Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, ni, 0 ); + + Vec1d uR; + uR.Allocate( 0, ni, 0 ); + + wenoL( ni, u, uL ); + wenoR( ni, u, uR ); + + for ( int i = 0; i < ni; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void WenoField::UpdateOldField() +{ + this->un = this->u; +} + +void WenoField::PostProcess( Grid * grid ) +{ + std::string csvname = std::format( "field_final{}.csv", Global::iter+1 ); + this->DumpField( csvname, grid->x, u ); +} + +void WenoField::DumpField( const std::string & filename, Vec1d & x, Vec1d & u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} {:.16f}", x[ i ], u[ i ] ); + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + + + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Weno.h new file mode 100644 index 00000000..afd57efe --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/Weno.h @@ -0,0 +1,40 @@ +#pragma once +#include "Vec1d.h" +#include "Field.h" +#include + +template +auto SQR(Args... args) { + return ( ... + ( args * args ) ); +} + +class WenoField : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + int ns; +public: + void Init( Grid * grid ); +public: + void PhysicalBoundary( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); + void Rhs( Vec1d & u, Vec1d & res ); +public: + void UpdateOldField(); + void PostProcess( Grid * grid ); + void DumpField( const std::string & filename, Vec1d & x, Vec1d & u ); +}; + +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/burgers1d1blocksv1.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/burgers1d1blocksv1.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/heat1d1block.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/heat1d1block.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/02i/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/CMakeLists.txt new file mode 100644 index 00000000..4892adaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/CgnsUtil.cpp new file mode 100644 index 00000000..3bcbd100 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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.Allocate( 0, nNodes - 1 ); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Field.cpp new file mode 100644 index 00000000..bf47a1e7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Field.cpp @@ -0,0 +1,311 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Field.h new file mode 100644 index 00000000..d0479a13 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Field.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} + virtual void PostProcess( Grid * grid ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Global.cpp new file mode 100644 index 00000000..dea5ff1c --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Global.cpp @@ -0,0 +1,308 @@ +#include "Global.h" +#include "Grid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::iter = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; +int Global::nghost = -1; + +std::vector Global::zones; +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 nghost ) +{ + 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 ); + + if ( i == 1 ) { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i - ig ); + ijk_donors.push_back( i + ig ); + } + } + else { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i + ig ); + ijk_donors.push_back( i - ig ); + } + } + + 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 * Global::nghost; + + for ( int ig = 0; ig < Global::nghost; ++ ig ) + { + int i_donor_cell = interface->ijk_donors[ ijkpos + ig ]; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Global.h new file mode 100644 index 00000000..eeb6ca18 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Global.h @@ -0,0 +1,107 @@ +#pragma once +#include "Vec1d.h" +#include +#include +#include +#include +#include +#include + +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, int nghost ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; +class Zone; +class Grid; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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 iter; + static int cell_dim; + static int phys_dim; + static int nghost; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Grid.cpp new file mode 100644 index 00000000..993ea5f9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Grid.cpp @@ -0,0 +1,274 @@ +#include "Grid.h" +#include "Vec1d.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( Vec1d &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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Grid.h new file mode 100644 index 00000000..b92a53ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Grid.h @@ -0,0 +1,110 @@ +#pragma once +#include "Vec1d.h" +#include +#include + +class Vec1d; + +class Grid +{ +public: + int zoneIndex; + Vec1d x; +}; + +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( Vec1d & 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/MyWenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/MyWenoPlot.py new file mode 100644 index 00000000..74dc3297 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/MyWenoPlot.py @@ -0,0 +1,46 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final0.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount +print("ni=",ni) + +ns = 10 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +for j in range(ns+1): + filename = 'field_final'+str((j)*250)+'.csv' + print('filename=',filename) + with open(filename, newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + x[i] = float(row[0]) + u[i][j] = float(row[1]) + i += 1 + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") +#exit() +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Post.cpp new file mode 100644 index 00000000..ef482e1f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Post.cpp @@ -0,0 +1,284 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include "Grid.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Solver.cpp new file mode 100644 index 00000000..d5271008 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Solver.cpp @@ -0,0 +1,513 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "Weno.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->nghost = 1; + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO; + this->nghost = 3; + Global::nghost = this->nghost; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + //this->PostProcess(); +} + +void Solver::ReadGrid() +{ + //std::string fileName = "../burgers1d1blocksv1.cgns"; + std::string fileName = "../burgers1d2blocks.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +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 = nullptr; + if ( scheme == Scheme::WENO ) { + field = new WenoField(); + } + else { + field = new FieldSub(); + } + 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::DumpInitialFields() +{ + this->PostProcess(); +} + +void Solver::SolveFields() +{ + this->DumpInitialFields(); + for ( int it = 0; it < Global::nt; ++ it ) + { + Global::iter = it; + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO: + this->RungeKutta(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + if ( ( Global::iter + 1 ) % 250 == 0 ) + { + std::print( "it = {} nt = {}\n", Global::iter + 1, Global::nt ); + this->PostProcess(); + } + + } +} + +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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + Field * field = Global::fields[ iZone ]; + + int nsend_zones = interface->send_to_zones.size(); + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = interface->send_to_zones[ iSend ]; + std::vector & donorfaces_for_send = interface->donorfaces_for_send[ iSend ]; + std::vector & donorijk_for_send = interface->donorijk_for_send[ iSend ]; + std::vector & donordata_for_send = interface->donordata_for_send[ iSend ]; + + int nInterFaces = donorfaces_for_send.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + int id_cell = donorijk_for_send[ ijkpos + ig ] - 1; + donordata_for_send[ data_pos + ig ] = field->u[ id_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 ]; + + int index_dim = 1; + + int ijkpos = index_dim * local_faceid * nghost; + int data_pos = local_faceid * nghost; + int donor_data_pos = i * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + double donor_value = donordata[ donor_data_pos + ig ]; + donor_interface->data_recv[ data_pos + ig ] = 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->zoneList.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + for ( int ig = 0; ig < nghost; ++ ig ) + { + int ig_cell = interface->ijk_ghosts[ ijkpos + ig ] - 1; + + double donor_value = interface->data_recv[ data_pos + ig ]; + field->u[ ig_cell ] = donor_value; + } + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + //Post post; + //post.Process(); + + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->PostProcess( grid ); + } +} + +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 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, this->nghost ); + } + int nInterfaces = interface->zoneList.size(); + int nData = nInterfaces * Global::nghost; + interface->data_recv.resize( nData ); + interface->data_send.resize( nData ); + } + + 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; +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Solver.h new file mode 100644 index 00000000..ef1e13b4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Solver.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; + int nghost; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); + void DumpInitialFields(); +public: + void Boundary(); + void UpdateOldField(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Weno.cpp new file mode 100644 index 00000000..7aa01855 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Weno.cpp @@ -0,0 +1,338 @@ +#include "Weno.h" +#include "Global.h" +#include "Grid.h" +#include "cgnslib.h" +#include +#include +#include +#include +#include + +void WenoField::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = 0.0001; + this->total_time = 0.25; + this->nt = std::round( total_time / dt ); + this->ns = 10; + + std::print( "ni={}\n",ni ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "total_time={}\n", total_time ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\n"; + + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + Global::nt = nt; + + int ighost = 3; + int ist = 0 - ighost; + int ied = this->ni - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + res.Allocate( 0, this->ni, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + int kkk = 1; +} + +void WenoField::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void WenoField::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 WenoField::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void WenoField::Rhs( Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, ni, 0 ); + + Vec1d uR; + uR.Allocate( 0, ni, 0 ); + + wenoL( ni, u, uL ); + wenoR( ni, u, uR ); + + for ( int i = 0; i < ni; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void WenoField::UpdateOldField() +{ + this->un = this->u; +} + +void WenoField::PostProcess( Grid * grid ) +{ + std::string csvname = std::format( "field_final{}.csv", Global::iter+1 ); + this->DumpField( csvname, grid->x, u ); +} + +void WenoField::DumpField( const std::string & filename, Vec1d & x, Vec1d & u ) +{ + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int i = 0; i < x.size(); ++ i ) + { + std::string str = {}; + str += std::format( "{:.16f} {:.16f}", x[ i ], u[ i ] ); + std::format_to(std::ostream_iterator(file), "{}\n", str ); + } + file.close(); +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + + + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Weno.h new file mode 100644 index 00000000..afd57efe --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/Weno.h @@ -0,0 +1,40 @@ +#pragma once +#include "Vec1d.h" +#include "Field.h" +#include + +template +auto SQR(Args... args) { + return ( ... + ( args * args ) ); +} + +class WenoField : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + int ns; +public: + void Init( Grid * grid ); +public: + void PhysicalBoundary( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); + void Rhs( Vec1d & u, Vec1d & res ); +public: + void UpdateOldField(); + void PostProcess( Grid * grid ); + void DumpField( const std::string & filename, Vec1d & x, Vec1d & u ); +}; + +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/burgers1d1blocksv1.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/burgers1d1blocksv1.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/burgers1d2blocks.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/burgers1d2blocks.cgns new file mode 100644 index 00000000..51518b5c Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/burgers1d2blocks.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/heat1d1block.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/heat1d1block.cgns new file mode 100644 index 00000000..b7d4954a Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/heat1d1block.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/CMakeLists.txt new file mode 100644 index 00000000..4892adaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/CgnsUtil.cpp new file mode 100644 index 00000000..3bcbd100 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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.Allocate( 0, nNodes - 1 ); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Field.cpp new file mode 100644 index 00000000..bf47a1e7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Field.cpp @@ -0,0 +1,311 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Field.h new file mode 100644 index 00000000..d0479a13 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Field.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} + virtual void PostProcess( Grid * grid ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Global.cpp new file mode 100644 index 00000000..f1ff5df1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Global.cpp @@ -0,0 +1,309 @@ +#include "Global.h" +#include "Grid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::iter = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; +int Global::nghost = -1; +std::string Global::file_string=""; + +std::vector Global::zones; +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 nghost ) +{ + 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 ); + + if ( i == 1 ) { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i - ig ); + ijk_donors.push_back( i + ig ); + } + } + else { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i + ig ); + ijk_donors.push_back( i - ig ); + } + } + + 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 * Global::nghost; + + for ( int ig = 0; ig < Global::nghost; ++ ig ) + { + int i_donor_cell = interface->ijk_donors[ ijkpos + ig ]; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Global.h new file mode 100644 index 00000000..5705ac34 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Global.h @@ -0,0 +1,108 @@ +#pragma once +#include "Vec1d.h" +#include +#include +#include +#include +#include +#include + +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, int nghost ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; +class Zone; +class Grid; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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 iter; + static int cell_dim; + static int phys_dim; + static int nghost; + static std::string file_string; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Grid.cpp new file mode 100644 index 00000000..993ea5f9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Grid.cpp @@ -0,0 +1,274 @@ +#include "Grid.h" +#include "Vec1d.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( Vec1d &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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Grid.h new file mode 100644 index 00000000..b92a53ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Grid.h @@ -0,0 +1,110 @@ +#pragma once +#include "Vec1d.h" +#include +#include + +class Vec1d; + +class Grid +{ +public: + int zoneIndex; + Vec1d x; +}; + +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( Vec1d & 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/MyWenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/MyWenoPlot.py new file mode 100644 index 00000000..74dc3297 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/MyWenoPlot.py @@ -0,0 +1,46 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final0.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount +print("ni=",ni) + +ns = 10 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +for j in range(ns+1): + filename = 'field_final'+str((j)*250)+'.csv' + print('filename=',filename) + with open(filename, newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + x[i] = float(row[0]) + u[i][j] = float(row[1]) + i += 1 + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") +#exit() +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Post.cpp new file mode 100644 index 00000000..ef482e1f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Post.cpp @@ -0,0 +1,284 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include "Grid.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Solver.cpp new file mode 100644 index 00000000..2221e307 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Solver.cpp @@ -0,0 +1,516 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "Weno.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->nghost = 1; + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO; + this->nghost = 3; + Global::nghost = this->nghost; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + //this->PostProcess(); +} + +void Solver::ReadGrid() +{ + //std::string fileName = "../burgers1d1blocksv1.cgns"; + std::string fileName = "../burgers1d2blocks.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +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 = nullptr; + if ( scheme == Scheme::WENO ) { + field = new WenoField(); + } + else { + field = new FieldSub(); + } + 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::DumpInitialFields() +{ + this->PostProcess(); +} + +void Solver::SolveFields() +{ + this->DumpInitialFields(); + for ( int it = 0; it < Global::nt; ++ it ) + { + Global::iter = it; + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO: + this->RungeKutta(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + if ( ( Global::iter + 1 ) % 250 == 0 ) + { + std::print( "it = {} nt = {}\n", Global::iter + 1, Global::nt ); + this->PostProcess(); + } + + } +} + +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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + Field * field = Global::fields[ iZone ]; + + int nsend_zones = interface->send_to_zones.size(); + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = interface->send_to_zones[ iSend ]; + std::vector & donorfaces_for_send = interface->donorfaces_for_send[ iSend ]; + std::vector & donorijk_for_send = interface->donorijk_for_send[ iSend ]; + std::vector & donordata_for_send = interface->donordata_for_send[ iSend ]; + + int nInterFaces = donorfaces_for_send.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + int id_cell = donorijk_for_send[ ijkpos + ig ] - 1; + donordata_for_send[ data_pos + ig ] = field->u[ id_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 ]; + + int index_dim = 1; + + int ijkpos = index_dim * local_faceid * nghost; + int data_pos = local_faceid * nghost; + int donor_data_pos = i * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + double donor_value = donordata[ donor_data_pos + ig ]; + donor_interface->data_recv[ data_pos + ig ] = 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->zoneList.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + for ( int ig = 0; ig < nghost; ++ ig ) + { + int ig_cell = interface->ijk_ghosts[ ijkpos + ig ] - 1; + + double donor_value = interface->data_recv[ data_pos + ig ]; + field->u[ ig_cell ] = donor_value; + } + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Global::file_string = {}; + std::string filename = std::format( "field_final{}.csv", Global::iter+1 ); + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->PostProcess( grid ); + } + std::format_to(std::ostream_iterator(file), "{}", Global::file_string ); + file.close(); +} + +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 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, this->nghost ); + } + int nInterfaces = interface->zoneList.size(); + int nData = nInterfaces * Global::nghost; + interface->data_recv.resize( nData ); + interface->data_send.resize( nData ); + } + + 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; +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Solver.h new file mode 100644 index 00000000..ef1e13b4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Solver.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; + int nghost; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); + void DumpInitialFields(); +public: + void Boundary(); + void UpdateOldField(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Weno.cpp new file mode 100644 index 00000000..ae4caab4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Weno.cpp @@ -0,0 +1,332 @@ +#include "Weno.h" +#include "Global.h" +#include "Grid.h" +#include "cgnslib.h" +#include +#include +#include +#include +#include + +void WenoField::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = 0.0001; + this->total_time = 0.25; + this->nt = std::round( total_time / dt ); + this->ns = 10; + + std::print( "ni={}\n",ni ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "total_time={}\n", total_time ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\n"; + + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + Global::nt = nt; + + int ighost = 3; + int ist = 0 - ighost; + int ied = this->ni - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + res.Allocate( 0, this->ni, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + int kkk = 1; +} + +void WenoField::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void WenoField::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 WenoField::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void WenoField::Rhs( Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, ni, 0 ); + + Vec1d uR; + uR.Allocate( 0, ni, 0 ); + + wenoL( ni, u, uL ); + wenoR( ni, u, uR ); + + for ( int i = 0; i < ni; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void WenoField::UpdateOldField() +{ + this->un = this->u; +} + +void WenoField::PostProcess( Grid * grid ) +{ + this->DumpField( grid->x, u ); +} + +void WenoField::DumpField( Vec1d & x, Vec1d & u ) +{ + for ( int i = 0; i < x.size(); ++ i ) + { + Global::file_string += std::format( "{:.16f} {:.16f}\n", x[ i ], u[ i ] ); + } +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + + + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Weno.h new file mode 100644 index 00000000..60dbf194 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/Weno.h @@ -0,0 +1,40 @@ +#pragma once +#include "Vec1d.h" +#include "Field.h" +#include + +template +auto SQR(Args... args) { + return ( ... + ( args * args ) ); +} + +class WenoField : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + int ns; +public: + void Init( Grid * grid ); +public: + void PhysicalBoundary( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); + void Rhs( Vec1d & u, Vec1d & res ); +public: + void UpdateOldField(); + void PostProcess( Grid * grid ); + void DumpField( Vec1d & x, Vec1d & u ); +}; + +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/burgers1d2blocks.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/burgers1d2blocks.cgns new file mode 100644 index 00000000..51518b5c Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/burgers1d2blocks.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/CMakeLists.txt new file mode 100644 index 00000000..4892adaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/CgnsUtil.cpp new file mode 100644 index 00000000..3bcbd100 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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.Allocate( 0, nNodes - 1 ); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Field.cpp new file mode 100644 index 00000000..bf47a1e7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Field.cpp @@ -0,0 +1,311 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Field.h new file mode 100644 index 00000000..d0479a13 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Field.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} + virtual void PostProcess( Grid * grid ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Global.cpp new file mode 100644 index 00000000..f1ff5df1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Global.cpp @@ -0,0 +1,309 @@ +#include "Global.h" +#include "Grid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::iter = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; +int Global::nghost = -1; +std::string Global::file_string=""; + +std::vector Global::zones; +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 nghost ) +{ + 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 ); + + if ( i == 1 ) { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i - ig ); + ijk_donors.push_back( i + ig ); + } + } + else { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i + ig ); + ijk_donors.push_back( i - ig ); + } + } + + 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 * Global::nghost; + + for ( int ig = 0; ig < Global::nghost; ++ ig ) + { + int i_donor_cell = interface->ijk_donors[ ijkpos + ig ]; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Global.h new file mode 100644 index 00000000..5705ac34 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Global.h @@ -0,0 +1,108 @@ +#pragma once +#include "Vec1d.h" +#include +#include +#include +#include +#include +#include + +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, int nghost ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; +class Zone; +class Grid; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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 iter; + static int cell_dim; + static int phys_dim; + static int nghost; + static std::string file_string; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Grid.cpp new file mode 100644 index 00000000..993ea5f9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Grid.cpp @@ -0,0 +1,274 @@ +#include "Grid.h" +#include "Vec1d.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( Vec1d &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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Grid.h new file mode 100644 index 00000000..b92a53ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Grid.h @@ -0,0 +1,110 @@ +#pragma once +#include "Vec1d.h" +#include +#include + +class Vec1d; + +class Grid +{ +public: + int zoneIndex; + Vec1d x; +}; + +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( Vec1d & 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/MyWenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/MyWenoPlot.py new file mode 100644 index 00000000..86418cff --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/MyWenoPlot.py @@ -0,0 +1,61 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final0.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount +print("ni=",ni) + +ns = 10 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +for j in range(ns+1): + filename = 'field_final'+str((j)*250)+'.csv' + print('filename=',filename) + with open(filename, newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + x[i] = float(row[0]) + u[i][j] = float(row[1]) + i += 1 + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") +#exit() +#x = np.linspace(0,1, num=ni) +#sort +sorted_indices = np.argsort(x) + +print("x=",x) +xt=x[sorted_indices] +print("xt=",xt) +ut=u[:,0] + +for k in range(ns+1): + for i in range(ni): + id = sorted_indices[i] + ut[i] = u[id,k] + for i in range(ni): + u[i,k] = ut[i] + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + #plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) + plt.plot(xt, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Post.cpp new file mode 100644 index 00000000..ef482e1f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Post.cpp @@ -0,0 +1,284 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include "Grid.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Solver.cpp new file mode 100644 index 00000000..30a11b18 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Solver.cpp @@ -0,0 +1,515 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "Weno.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->nghost = 1; + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO; + this->nghost = 3; + Global::nghost = this->nghost; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + //this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../burgers1d4blocks.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +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 = nullptr; + if ( scheme == Scheme::WENO ) { + field = new WenoField(); + } + else { + field = new FieldSub(); + } + 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::DumpInitialFields() +{ + this->PostProcess(); +} + +void Solver::SolveFields() +{ + this->DumpInitialFields(); + for ( int it = 0; it < Global::nt; ++ it ) + { + Global::iter = it; + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO: + this->RungeKutta(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + if ( ( Global::iter + 1 ) % 250 == 0 ) + { + std::print( "it = {} nt = {}\n", Global::iter + 1, Global::nt ); + this->PostProcess(); + } + + } +} + +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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + Field * field = Global::fields[ iZone ]; + + int nsend_zones = interface->send_to_zones.size(); + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = interface->send_to_zones[ iSend ]; + std::vector & donorfaces_for_send = interface->donorfaces_for_send[ iSend ]; + std::vector & donorijk_for_send = interface->donorijk_for_send[ iSend ]; + std::vector & donordata_for_send = interface->donordata_for_send[ iSend ]; + + int nInterFaces = donorfaces_for_send.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + int id_cell = donorijk_for_send[ ijkpos + ig ] - 1; + donordata_for_send[ data_pos + ig ] = field->u[ id_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 ]; + + int index_dim = 1; + + int ijkpos = index_dim * local_faceid * nghost; + int data_pos = local_faceid * nghost; + int donor_data_pos = i * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + double donor_value = donordata[ donor_data_pos + ig ]; + donor_interface->data_recv[ data_pos + ig ] = 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->zoneList.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + for ( int ig = 0; ig < nghost; ++ ig ) + { + int ig_cell = interface->ijk_ghosts[ ijkpos + ig ] - 1; + + double donor_value = interface->data_recv[ data_pos + ig ]; + field->u[ ig_cell ] = donor_value; + } + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Global::file_string = {}; + std::string filename = std::format( "field_final{}.csv", Global::iter+1 ); + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->PostProcess( grid ); + } + std::format_to(std::ostream_iterator(file), "{}", Global::file_string ); + file.close(); +} + +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 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, this->nghost ); + } + int nInterfaces = interface->zoneList.size(); + int nData = nInterfaces * Global::nghost; + interface->data_recv.resize( nData ); + interface->data_send.resize( nData ); + } + + 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; +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Solver.h new file mode 100644 index 00000000..ef1e13b4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Solver.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; + int nghost; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); + void DumpInitialFields(); +public: + void Boundary(); + void UpdateOldField(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Weno.cpp new file mode 100644 index 00000000..ae4caab4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Weno.cpp @@ -0,0 +1,332 @@ +#include "Weno.h" +#include "Global.h" +#include "Grid.h" +#include "cgnslib.h" +#include +#include +#include +#include +#include + +void WenoField::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = 0.0001; + this->total_time = 0.25; + this->nt = std::round( total_time / dt ); + this->ns = 10; + + std::print( "ni={}\n",ni ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "total_time={}\n", total_time ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\n"; + + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + Global::nt = nt; + + int ighost = 3; + int ist = 0 - ighost; + int ied = this->ni - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + res.Allocate( 0, this->ni, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + int kkk = 1; +} + +void WenoField::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void WenoField::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 WenoField::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void WenoField::Rhs( Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, ni, 0 ); + + Vec1d uR; + uR.Allocate( 0, ni, 0 ); + + wenoL( ni, u, uL ); + wenoR( ni, u, uR ); + + for ( int i = 0; i < ni; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void WenoField::UpdateOldField() +{ + this->un = this->u; +} + +void WenoField::PostProcess( Grid * grid ) +{ + this->DumpField( grid->x, u ); +} + +void WenoField::DumpField( Vec1d & x, Vec1d & u ) +{ + for ( int i = 0; i < x.size(); ++ i ) + { + Global::file_string += std::format( "{:.16f} {:.16f}\n", x[ i ], u[ i ] ); + } +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + + + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Weno.h new file mode 100644 index 00000000..60dbf194 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/Weno.h @@ -0,0 +1,40 @@ +#pragma once +#include "Vec1d.h" +#include "Field.h" +#include + +template +auto SQR(Args... args) { + return ( ... + ( args * args ) ); +} + +class WenoField : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + int ns; +public: + void Init( Grid * grid ); +public: + void PhysicalBoundary( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); + void Rhs( Vec1d & u, Vec1d & res ); +public: + void UpdateOldField(); + void PostProcess( Grid * grid ); + void DumpField( Vec1d & x, Vec1d & u ); +}; + +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/burgers1d4blocks.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/burgers1d4blocks.cgns new file mode 100644 index 00000000..3585da45 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/burgers1d4blocks.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03b/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/CMakeLists.txt new file mode 100644 index 00000000..57668e60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/CMakeLists.txt @@ -0,0 +1,84 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/CgnsUtil.cpp new file mode 100644 index 00000000..3bcbd100 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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.Allocate( 0, nNodes - 1 ); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Field.cpp new file mode 100644 index 00000000..bf47a1e7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Field.cpp @@ -0,0 +1,311 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Field.h new file mode 100644 index 00000000..d0479a13 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Field.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} + virtual void PostProcess( Grid * grid ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Global.cpp new file mode 100644 index 00000000..f1ff5df1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Global.cpp @@ -0,0 +1,309 @@ +#include "Global.h" +#include "Grid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::iter = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; +int Global::nghost = -1; +std::string Global::file_string=""; + +std::vector Global::zones; +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 nghost ) +{ + 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 ); + + if ( i == 1 ) { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i - ig ); + ijk_donors.push_back( i + ig ); + } + } + else { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i + ig ); + ijk_donors.push_back( i - ig ); + } + } + + 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 * Global::nghost; + + for ( int ig = 0; ig < Global::nghost; ++ ig ) + { + int i_donor_cell = interface->ijk_donors[ ijkpos + ig ]; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Global.h new file mode 100644 index 00000000..5705ac34 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Global.h @@ -0,0 +1,108 @@ +#pragma once +#include "Vec1d.h" +#include +#include +#include +#include +#include +#include + +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, int nghost ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; +class Zone; +class Grid; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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 iter; + static int cell_dim; + static int phys_dim; + static int nghost; + static std::string file_string; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Grid.cpp new file mode 100644 index 00000000..993ea5f9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Grid.cpp @@ -0,0 +1,274 @@ +#include "Grid.h" +#include "Vec1d.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( Vec1d &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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Grid.h new file mode 100644 index 00000000..b92a53ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Grid.h @@ -0,0 +1,110 @@ +#pragma once +#include "Vec1d.h" +#include +#include + +class Vec1d; + +class Grid +{ +public: + int zoneIndex; + Vec1d x; +}; + +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( Vec1d & 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/MyWenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/MyWenoPlot.py new file mode 100644 index 00000000..b44106d1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/MyWenoPlot.py @@ -0,0 +1,53 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final0.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount +print("ni=",ni) + +ns = 10 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +for j in range(ns+1): + filename = 'field_final'+str((j)*250)+'.csv' + print('filename=',filename) + with open(filename, newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + x[i] = float(row[0]) + u[i][j] = float(row[1]) + i += 1 + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") +#exit() +#x = np.linspace(0,1, num=ni) + +#sort +sorted_indices = np.argsort(x) +xt=x[sorted_indices] + +for k in range(ns+1): + ut = u[sorted_indices,k] + u[:,k] = ut[:] +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(xt, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Parallel.cpp new file mode 100644 index 00000000..0bce1a60 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Parallel.h new file mode 100644 index 00000000..880a71cb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Post.cpp new file mode 100644 index 00000000..ef482e1f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Post.cpp @@ -0,0 +1,284 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include "Grid.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Solver.cpp new file mode 100644 index 00000000..39fe5b9c --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Solver.cpp @@ -0,0 +1,513 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "Weno.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->nghost = 1; + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO; + this->nghost = 3; + Global::nghost = this->nghost; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + //this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../burgers1d4blocks.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +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 = nullptr; + if ( scheme == Scheme::WENO ) { + field = new WenoField(); + } + else { + field = new FieldSub(); + } + 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::DumpInitialFields() +{ + this->PostProcess(); +} + +void Solver::SolveFields() +{ + this->DumpInitialFields(); + for ( int it = 0; it < Global::nt; ++ it ) + { + Global::iter = it; + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO: + this->RungeKutta(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + if ( ( Global::iter + 1 ) % 250 == 0 ) + { + std::print( "it = {} nt = {}\n", Global::iter + 1, Global::nt ); + this->PostProcess(); + } + + } +} + +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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + Field * field = Global::fields[ iZone ]; + + int nsend_zones = interface->send_to_zones.size(); + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = interface->send_to_zones[ iSend ]; + std::vector & donorfaces_for_send = interface->donorfaces_for_send[ iSend ]; + std::vector & donorijk_for_send = interface->donorijk_for_send[ iSend ]; + std::vector & donordata_for_send = interface->donordata_for_send[ iSend ]; + + int nInterFaces = donorfaces_for_send.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + int id_cell = donorijk_for_send[ ijkpos + ig ] - 1; + donordata_for_send[ data_pos + ig ] = field->u[ id_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 ]; + + int index_dim = 1; + + int ijkpos = index_dim * local_faceid * nghost; + int data_pos = local_faceid * nghost; + int donor_data_pos = i * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + double donor_value = donordata[ donor_data_pos + ig ]; + donor_interface->data_recv[ data_pos + ig ] = 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->zoneList.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + for ( int ig = 0; ig < nghost; ++ ig ) + { + int ig_cell = interface->ijk_ghosts[ ijkpos + ig ] - 1; + + double donor_value = interface->data_recv[ data_pos + ig ]; + field->u[ ig_cell ] = donor_value; + } + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + Global::file_string = {}; + std::string filename = std::format( "field_final{}.csv", Global::iter+1 ); + std::fstream file; + file.open( filename.c_str(), std::fstream::out ); + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Grid * grid = Global::grids[ iZone ]; + Field * field = Global::fields[ iZone ]; + field->PostProcess( grid ); + } + std::format_to(std::ostream_iterator(file), "{}", Global::file_string ); + file.close(); +} + +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 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, this->nghost ); + } + int nInterfaces = interface->zoneList.size(); + int nData = nInterfaces * Global::nghost; + interface->data_recv.resize( nData ); + interface->data_send.resize( nData ); + } + + 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(); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Solver.h new file mode 100644 index 00000000..ef1e13b4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Solver.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; + int nghost; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); + void DumpInitialFields(); +public: + void Boundary(); + void UpdateOldField(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Weno.cpp new file mode 100644 index 00000000..e4f1c1ae --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Weno.cpp @@ -0,0 +1,330 @@ +#include "Weno.h" +#include "Global.h" +#include "Grid.h" +#include "cgnslib.h" +#include +#include +#include +#include +#include + +void WenoField::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = 0.0001; + this->total_time = 0.25; + this->nt = std::round( total_time / dt ); + this->ns = 10; + + std::print( "ni={}\n",ni ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "total_time={}\n", total_time ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\n"; + + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + Global::nt = nt; + + int ighost = 3; + int ist = 0 - ighost; + int ied = this->ni - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + res.Allocate( 0, this->ni, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + int kkk = 1; +} + +void WenoField::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void WenoField::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 WenoField::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void WenoField::Rhs( Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, ni, 0 ); + + Vec1d uR; + uR.Allocate( 0, ni, 0 ); + + wenoL( ni, u, uL ); + wenoR( ni, u, uR ); + + for ( int i = 0; i < ni; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void WenoField::UpdateOldField() +{ + this->un = this->u; +} + +void WenoField::PostProcess( Grid * grid ) +{ + this->DumpField( grid->x, u ); +} + +void WenoField::DumpField( Vec1d & x, Vec1d & u ) +{ + for ( int i = 0; i < x.size(); ++ i ) + { + Global::file_string += std::format( "{:.16f} {:.16f}\n", x[ i ], u[ i ] ); + } +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Weno.h new file mode 100644 index 00000000..60dbf194 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/Weno.h @@ -0,0 +1,40 @@ +#pragma once +#include "Vec1d.h" +#include "Field.h" +#include + +template +auto SQR(Args... args) { + return ( ... + ( args * args ) ); +} + +class WenoField : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + int ns; +public: + void Init( Grid * grid ); +public: + void PhysicalBoundary( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); + void Rhs( Vec1d & u, Vec1d & res ); +public: + void UpdateOldField(); + void PostProcess( Grid * grid ); + void DumpField( Vec1d & x, Vec1d & u ); +}; + +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/burgers1d4blocks.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/burgers1d4blocks.cgns new file mode 100644 index 00000000..3585da45 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/burgers1d4blocks.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/03c/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/CMakeLists.txt new file mode 100644 index 00000000..9f1f2eaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/CMakeLists.txt @@ -0,0 +1,96 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/CgnsUtil.cpp new file mode 100644 index 00000000..3bcbd100 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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.Allocate( 0, nNodes - 1 ); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Field.cpp new file mode 100644 index 00000000..bf47a1e7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Field.cpp @@ -0,0 +1,311 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Field.h new file mode 100644 index 00000000..d0479a13 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Field.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} + virtual void PostProcess( Grid * grid ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Global.cpp new file mode 100644 index 00000000..f1ff5df1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Global.cpp @@ -0,0 +1,309 @@ +#include "Global.h" +#include "Grid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::iter = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; +int Global::nghost = -1; +std::string Global::file_string=""; + +std::vector Global::zones; +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 nghost ) +{ + 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 ); + + if ( i == 1 ) { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i - ig ); + ijk_donors.push_back( i + ig ); + } + } + else { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i + ig ); + ijk_donors.push_back( i - ig ); + } + } + + 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 * Global::nghost; + + for ( int ig = 0; ig < Global::nghost; ++ ig ) + { + int i_donor_cell = interface->ijk_donors[ ijkpos + ig ]; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Global.h new file mode 100644 index 00000000..5705ac34 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Global.h @@ -0,0 +1,108 @@ +#pragma once +#include "Vec1d.h" +#include +#include +#include +#include +#include +#include + +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, int nghost ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; +class Zone; +class Grid; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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 iter; + static int cell_dim; + static int phys_dim; + static int nghost; + static std::string file_string; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Grid.cpp new file mode 100644 index 00000000..993ea5f9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Grid.cpp @@ -0,0 +1,274 @@ +#include "Grid.h" +#include "Vec1d.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( Vec1d &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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Grid.h new file mode 100644 index 00000000..b92a53ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Grid.h @@ -0,0 +1,110 @@ +#pragma once +#include "Vec1d.h" +#include +#include + +class Vec1d; + +class Grid +{ +public: + int zoneIndex; + Vec1d x; +}; + +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( Vec1d & 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/MyWenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/MyWenoPlot.py new file mode 100644 index 00000000..b44106d1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/MyWenoPlot.py @@ -0,0 +1,53 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final0.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount +print("ni=",ni) + +ns = 10 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +for j in range(ns+1): + filename = 'field_final'+str((j)*250)+'.csv' + print('filename=',filename) + with open(filename, newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + x[i] = float(row[0]) + u[i][j] = float(row[1]) + i += 1 + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") +#exit() +#x = np.linspace(0,1, num=ni) + +#sort +sorted_indices = np.argsort(x) +xt=x[sorted_indices] + +for k in range(ns+1): + ut = u[sorted_indices,k] + u[:,k] = ut[:] +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(xt, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Parallel.cpp new file mode 100644 index 00000000..d3ee1dfa --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Parallel.cpp @@ -0,0 +1,106 @@ +#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 +} + +void HXSendString( std::string const & str, int recv_pid, int tag ) +{ +#ifdef HX_PARALLEL + unsigned len = str.size(); + MPI_Send( &len, 1, MPI_UNSIGNED, recv_pid, tag, MPI_COMM_WORLD ); + if ( len == 0 ) return; + MPI_Send( str.data(), len, MPI_CHAR, recv_pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvString( std::string & str, int send_pid, int tag ) +{ +#ifdef HX_PARALLEL + unsigned len; + MPI_Status status; + MPI_Recv( &len, 1, MPI_UNSIGNED, send_pid, tag, MPI_COMM_WORLD, &status ); + if ( len == 0 ) return; + str.resize( len ); + MPI_Recv( str.data(), len, MPI_CHAR, send_pid, tag, MPI_COMM_WORLD, &status ); +#endif +} + +void HXSendRecvString( std::string & str, int send_pid, int recv_pid, int tag ) +{ + if ( send_pid == recv_pid ) return; + if ( Parallel::pid == send_pid ) + { + HXSendString( str, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvString( str, send_pid, tag ); + } +} + + +//void HXSendRecvString( std::string & str, int send_pid, int recv_pid, int tag ) +//{ +// if ( send_pid == recv_pid ) return; +// int nsize = -1; +// if ( Parallel::pid == send_pid ) +// { +// nsize = str.size(); +// } +// HXSendRecvData( &nsize, 1, send_pid, recv_pid, tag ); +// if ( Parallel::pid == recv_pid ) +// { +// str.resize( nsize ); +// } +// HXSendRecvData( str.data(), nsize, send_pid, recv_pid, tag ); +//} +// diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Parallel.h new file mode 100644 index 00000000..c104bca8 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Parallel.h @@ -0,0 +1,81 @@ +#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 = 0 ); +void HXRecvChar( void * data, int size, int pid, int tag = 0 ); +void HXSendRecvString( std::string & str, int send_pid, int recv_pid, int tag = 0 ); +void HXSendString( std::string const & str, int recv_pid, int tag = 0 ); +void HXRecvString( std::string & str, int send_pid, int tag = 0 ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Post.cpp new file mode 100644 index 00000000..ef482e1f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Post.cpp @@ -0,0 +1,284 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include "Grid.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Solver.cpp new file mode 100644 index 00000000..08828986 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Solver.cpp @@ -0,0 +1,536 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "Weno.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->nghost = 1; + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO; + this->nghost = 3; + Global::nghost = this->nghost; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + //this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../burgers1d4blocks.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +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 = nullptr; + if ( scheme == Scheme::WENO ) { + field = new WenoField(); + } + else { + field = new FieldSub(); + } + 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::DumpInitialFields() +{ + this->PostProcess(); +} + +void Solver::SolveFields() +{ + this->DumpInitialFields(); + for ( int it = 0; it < Global::nt; ++ it ) + { + Global::iter = it; + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO: + this->RungeKutta(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + if ( ( Global::iter + 1 ) % 250 == 0 ) + { + std::print( "it = {} nt = {}\n", Global::iter + 1, Global::nt ); + this->PostProcess(); + } + + } +} + +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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + Field * field = Global::fields[ iZone ]; + + int nsend_zones = interface->send_to_zones.size(); + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = interface->send_to_zones[ iSend ]; + std::vector & donorfaces_for_send = interface->donorfaces_for_send[ iSend ]; + std::vector & donorijk_for_send = interface->donorijk_for_send[ iSend ]; + std::vector & donordata_for_send = interface->donordata_for_send[ iSend ]; + + int nInterFaces = donorfaces_for_send.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + int id_cell = donorijk_for_send[ ijkpos + ig ] - 1; + donordata_for_send[ data_pos + ig ] = field->u[ id_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 ]; + + int index_dim = 1; + + int ijkpos = index_dim * local_faceid * nghost; + int data_pos = local_faceid * nghost; + int donor_data_pos = i * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + double donor_value = donordata[ donor_data_pos + ig ]; + donor_interface->data_recv[ data_pos + ig ] = 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->zoneList.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + for ( int ig = 0; ig < nghost; ++ ig ) + { + int ig_cell = interface->ijk_ghosts[ ijkpos + ig ] - 1; + + double donor_value = interface->data_recv[ data_pos + ig ]; + field->u[ ig_cell ] = donor_value; + } + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + std::string total_string = {}; + std::fstream file; + if ( Parallel::pid == Parallel::serverid ) + { + std::string filename = std::format( "field_final{}.csv", Global::iter+1 ); + file.open( filename.c_str(), std::fstream::out ); + } + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = Parallel::serverid; + + Global::file_string = {}; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + field->PostProcess( grid ); + } + + HXSendRecvString( Global::file_string, send_pid, Parallel::serverid ); + + if ( Parallel::pid == Parallel::serverid ) + { + total_string += Global::file_string; + } + } + if ( Parallel::pid == Parallel::serverid ) + { + std::format_to( std::ostream_iterator( file ), "{}", total_string ); + file.close(); + } +} + +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 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, this->nghost ); + } + int nInterfaces = interface->zoneList.size(); + int nData = nInterfaces * Global::nghost; + interface->data_recv.resize( nData ); + interface->data_send.resize( nData ); + } + + 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(); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Solver.h new file mode 100644 index 00000000..ef1e13b4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Solver.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; + int nghost; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); + void DumpInitialFields(); +public: + void Boundary(); + void UpdateOldField(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Weno.cpp new file mode 100644 index 00000000..e4f1c1ae --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Weno.cpp @@ -0,0 +1,330 @@ +#include "Weno.h" +#include "Global.h" +#include "Grid.h" +#include "cgnslib.h" +#include +#include +#include +#include +#include + +void WenoField::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = 0.0001; + this->total_time = 0.25; + this->nt = std::round( total_time / dt ); + this->ns = 10; + + std::print( "ni={}\n",ni ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "total_time={}\n", total_time ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\n"; + + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + Global::nt = nt; + + int ighost = 3; + int ist = 0 - ighost; + int ied = this->ni - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + res.Allocate( 0, this->ni, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + int kkk = 1; +} + +void WenoField::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void WenoField::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 WenoField::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void WenoField::Rhs( Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, ni, 0 ); + + Vec1d uR; + uR.Allocate( 0, ni, 0 ); + + wenoL( ni, u, uL ); + wenoR( ni, u, uR ); + + for ( int i = 0; i < ni; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void WenoField::UpdateOldField() +{ + this->un = this->u; +} + +void WenoField::PostProcess( Grid * grid ) +{ + this->DumpField( grid->x, u ); +} + +void WenoField::DumpField( Vec1d & x, Vec1d & u ) +{ + for ( int i = 0; i < x.size(); ++ i ) + { + Global::file_string += std::format( "{:.16f} {:.16f}\n", x[ i ], u[ i ] ); + } +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Weno.h new file mode 100644 index 00000000..60dbf194 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/Weno.h @@ -0,0 +1,40 @@ +#pragma once +#include "Vec1d.h" +#include "Field.h" +#include + +template +auto SQR(Args... args) { + return ( ... + ( args * args ) ); +} + +class WenoField : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + int ns; +public: + void Init( Grid * grid ); +public: + void PhysicalBoundary( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); + void Rhs( Vec1d & u, Vec1d & res ); +public: + void UpdateOldField(); + void PostProcess( Grid * grid ); + void DumpField( Vec1d & x, Vec1d & u ); +}; + +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/burgers1d4blocks.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/burgers1d4blocks.cgns new file mode 100644 index 00000000..3585da45 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/burgers1d4blocks.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/CMakeLists.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/CMakeLists.txt new file mode 100644 index 00000000..9f1f2eaf --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/CMakeLists.txt @@ -0,0 +1,96 @@ +cmake_minimum_required(VERSION 3.31) + +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 ) + +message ( STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}" ) + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +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 + Vec1d.h + CgnsUtil.h CgnsUtil.cpp + Field.h Field.cpp + Global.h Global.cpp + Grid.h Grid.cpp + LogFile.h LogFile.cpp + Parallel.h Parallel.cpp + Post.h Post.cpp + Solver.h Solver.cpp + Weno.h Weno.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/CgnsUtil.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/CgnsUtil.cpp new file mode 100644 index 00000000..3bcbd100 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/CgnsUtil.cpp @@ -0,0 +1,584 @@ +#include "CgnsUtil.h" +#include "Global.h" +#include "Grid.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "cgnslib.h" +#include +#include + +BaseZoneList global_zone_names; + +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 ); + } + 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"; + + 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.Allocate( 0, nNodes - 1 ); + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/CgnsUtil.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/CgnsUtil.h new file mode 100644 index 00000000..dba4a529 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/CgnsUtil.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +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; + } +}; + +void ReadCgnsGridBaseZone( const std::string & filename ); +void ReadCgnsGrid( const std::string & filename ); \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Field.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Field.cpp new file mode 100644 index 00000000..bf47a1e7 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Field.cpp @@ -0,0 +1,311 @@ +#include "Field.h" +#include "Grid.h" +#include "Global.h" +#include "cgnslib.h" +#include +#include + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void FieldSub::Init( Grid * grid ) +{ + this->InitHeatEquation( grid ); +} + +void FieldSub::InitHeatEquation( Grid * grid ) +{ + this->ni = grid->x.size(); + std::cout << "ni = " << ni << "\n"; + + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = dx / 10.0; + this->total_time = 1.0; + this->nt = std::round( total_time / dt ); + + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\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; + + int N = this->ni; + + int ighost = 1; + int iist = 0 - ighost; + int iied = N - 1 + ighost; + u_e.Allocate( iist, iied ); + u.Allocate( iist, iied ); + un.Allocate( iist, iied ); + res.Allocate( 0, N, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + double xm = x[ i ]; + 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 FieldSub::FTCS( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::CN( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = - rr; + b[ i ] = 1.0 + 2.0 * rr; + c[ i ] = - rr; + } + + for ( int i = 0; i < ni; ++ i ) + { + d[ i ] = rr * u[ i - 1 ] + ( 1.0 - 2.0 * rr ) * u[ i ] + rr * u[ i + 1 ]; + } + + a[ 0 ] = 0; + c[ ni - 1 ] = 0; + + d[ 0 ] -= ( - rr ) * u[ 0 ]; + d[ ni - 1 ] -= ( - rr ) * u[ ni + 1 ]; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::ICP( Zone * zone ) +{ + double rr = 0.5 * this->alpha * dt / ( dx * dx ); + std::vector a( ni );//0:ni-1 + std::vector b( ni );//0:ni-1 + std::vector c( ni );//0:ni-1 + std::vector d( ni );//0:ni-1 + + for ( int i = 0; i < ni; ++ i ) + { + a[ i ] = 1.0 / 12.0 - rr; + b[ i ] = 10.0 / 12.0 + 2.0 * rr; + c[ i ] = 1.0 / 12.0 - rr; + } + + a[ 0 ] = 0; + b[ 0 ] = 1; + c[ 0 ] = 0; + + a[ ni - 1 ] = 0; + b[ ni - 1 ] = 1; + c[ ni - 1 ] = 0; + + for ( int i = 0; i < ni; ++ i ) + { + double aa = 1.0 / 12.0 + rr; + double bb = 10.0 / 12.0 - 2.0 * rr; + double cc = 1.0 / 12.0 + rr; + d[ i ] = aa * u[ i - 1 ] + bb * u[ i ] + cc * u[ i + 1 ]; + } + + d[ 0 ] = 0; + d[ ni - 1 ] = 0; + + std::vector values( d.size() ); + + thomas_algorithm( a, b, c, d, values ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = values[ i ]; + } +} + +void FieldSub::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 FieldSub::UpdateOldField() +{ + this->un = this->u; +} + +void FieldSub::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void FieldSub::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void FieldSub::Rhs( Vec1d & u, Vec1d & r ) +{ + double coef = this->alpha / ( dx * dx ); + + for ( int i = 0; i < ni; ++ i ) + { + r[ i ] = coef * ( u[ i + 1 ] - 2.0 * u[ i ] + u[ i - 1 ] ); + } +} + +void FieldSub::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void FieldSub::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + int kkk = 1; + } +} + +void FieldSub::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 ii = i - 1; //index from 0 + int ighost = ii + idir; + int iinner = ii - idir; + //this->u[ ighost ] = 2 * this->u[ i ] - this->u[ iinner ]; + this->u[ ighost ] = - this->u[ iinner ]; + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Field.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Field.h new file mode 100644 index 00000000..d0479a13 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Field.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include "Vec1d.h" + +class Zone; +class Grid; +class Region; + +class Field +{ +public: + Field() {} + virtual ~Field() {}; +public: + virtual void Init( Grid * grid ) {} + virtual void UpdateOldField() {} + virtual void FTCS( Zone * zone ) {} + virtual void CN( Zone * zone ) {} + virtual void ICP( Zone * zone ) {} + virtual void RungeKutta( Zone * zone, int istage ) {} + virtual void PhysicalBoundary( Zone * zone ) {} + virtual void PostProcess( Grid * grid ) {} +public: + Vec1d u_e; + Vec1d u, un; + Vec1d res; +}; + +class FieldSub : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + double alpha, beta; +public: + void Init( Grid * grid ); + void InitHeatEquation( Grid * grid ); +public: + void FTCS( Zone * zone ); + void CN( Zone * zone ); + void ICP( Zone * zone ); + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); +public: + void Rhs( Vec1d & u, Vec1d & r ); + + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); + + void PhysicalBoundary( Zone * zone ); + void UpdateOldField(); +}; + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Global.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Global.cpp new file mode 100644 index 00000000..f1ff5df1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Global.cpp @@ -0,0 +1,309 @@ +#include "Global.h" +#include "Grid.h" +#include "ZoneState.h" +#include "Parallel.h" +#include + +std::vector Global::grids; +std::vector Global::fields; + +int Global::nt = -1; +int Global::iter = -1; +int Global::cell_dim = -1; +int Global::phys_dim = -1; +int Global::nghost = -1; +std::string Global::file_string=""; + +std::vector Global::zones; +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 nghost ) +{ + 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 ); + + if ( i == 1 ) { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i - ig ); + ijk_donors.push_back( i + ig ); + } + } + else { + for ( int ig = 1; ig <= nghost; ++ ig ) + { + ijk_ghosts.push_back( i + ig ); + ijk_donors.push_back( i - ig ); + } + } + + 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 * Global::nghost; + + for ( int ig = 0; ig < Global::nghost; ++ ig ) + { + int i_donor_cell = interface->ijk_donors[ ijkpos + ig ]; + 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Global.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Global.h new file mode 100644 index 00000000..5705ac34 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Global.h @@ -0,0 +1,108 @@ +#pragma once +#include "Vec1d.h" +#include +#include +#include +#include +#include +#include + +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, int nghost ); + void SendGeom( int zone, std::vector & donorfaces ); +}; + +class Field; +class InterFaceZone; +class Zone; +class Grid; + +class Global +{ +public: + static std::vector grids; + static std::vector fields; +public: + static std::vector zones; + 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 iter; + static int cell_dim; + static int phys_dim; + static int nghost; + static std::string file_string; +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Grid.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Grid.cpp new file mode 100644 index 00000000..993ea5f9 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Grid.cpp @@ -0,0 +1,274 @@ +#include "Grid.h" +#include "Vec1d.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( Vec1d &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 ]; + } + } +} diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Grid.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Grid.h new file mode 100644 index 00000000..b92a53ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Grid.h @@ -0,0 +1,110 @@ +#pragma once +#include "Vec1d.h" +#include +#include + +class Vec1d; + +class Grid +{ +public: + int zoneIndex; + Vec1d x; +}; + +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( Vec1d & 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 ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/LogFile.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/LogFile.cpp new file mode 100644 index 00000000..08ccd453 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/LogFile.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/LogFile.h new file mode 100644 index 00000000..00e775ab --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/MyWenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/MyWenoPlot.py new file mode 100644 index 00000000..b44106d1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/MyWenoPlot.py @@ -0,0 +1,53 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final0.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount +print("ni=",ni) + +ns = 10 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +for j in range(ns+1): + filename = 'field_final'+str((j)*250)+'.csv' + print('filename=',filename) + with open(filename, newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + x[i] = float(row[0]) + u[i][j] = float(row[1]) + i += 1 + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") +#exit() +#x = np.linspace(0,1, num=ni) + +#sort +sorted_indices = np.argsort(x) +xt=x[sorted_indices] + +for k in range(ns+1): + ut = u[sorted_indices,k] + u[:,k] = ut[:] +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(xt, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Parallel.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Parallel.cpp new file mode 100644 index 00000000..d3ee1dfa --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Parallel.cpp @@ -0,0 +1,106 @@ +#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 +} + +void HXSendString( std::string const & str, int recv_pid, int tag ) +{ +#ifdef HX_PARALLEL + unsigned len = str.size(); + MPI_Send( &len, 1, MPI_UNSIGNED, recv_pid, tag, MPI_COMM_WORLD ); + if ( len == 0 ) return; + MPI_Send( str.data(), len, MPI_CHAR, recv_pid, tag, MPI_COMM_WORLD ); +#endif +} + +void HXRecvString( std::string & str, int send_pid, int tag ) +{ +#ifdef HX_PARALLEL + unsigned len; + MPI_Status status; + MPI_Recv( &len, 1, MPI_UNSIGNED, send_pid, tag, MPI_COMM_WORLD, &status ); + if ( len == 0 ) return; + str.resize( len ); + MPI_Recv( str.data(), len, MPI_CHAR, send_pid, tag, MPI_COMM_WORLD, &status ); +#endif +} + +void HXSendRecvString( std::string & str, int send_pid, int recv_pid, int tag ) +{ + if ( send_pid == recv_pid ) return; + if ( Parallel::pid == send_pid ) + { + HXSendString( str, recv_pid, tag ); + } + else if ( Parallel::pid == recv_pid ) + { + HXRecvString( str, send_pid, tag ); + } +} + + +//void HXSendRecvString( std::string & str, int send_pid, int recv_pid, int tag ) +//{ +// if ( send_pid == recv_pid ) return; +// int nsize = -1; +// if ( Parallel::pid == send_pid ) +// { +// nsize = str.size(); +// } +// HXSendRecvData( &nsize, 1, send_pid, recv_pid, tag ); +// if ( Parallel::pid == recv_pid ) +// { +// str.resize( nsize ); +// } +// HXSendRecvData( str.data(), nsize, send_pid, recv_pid, tag ); +//} +// diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Parallel.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Parallel.h new file mode 100644 index 00000000..c104bca8 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Parallel.h @@ -0,0 +1,81 @@ +#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 = 0 ); +void HXRecvChar( void * data, int size, int pid, int tag = 0 ); +void HXSendRecvString( std::string & str, int send_pid, int recv_pid, int tag = 0 ); +void HXSendString( std::string const & str, int recv_pid, int tag = 0 ); +void HXRecvString( std::string & str, int send_pid, int tag = 0 ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Post.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Post.cpp new file mode 100644 index 00000000..ef482e1f --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Post.cpp @@ -0,0 +1,284 @@ +#include "Post.h" +#include "Parallel.h" +#include "ZoneState.h" +#include "Global.h" +#include "Field.h" +#include "Grid.h" +#include +#include +#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 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 dir = 1; + if ( grid->x[ 0 ] > grid->x[ 1 ] ) dir = -1; + + if ( dir == 1 ) + { + if ( IsLastZone( iZone ) ) + { + for ( int i = 0; i < ni; ++ i ) + { + double xm = grid->x[ i ]; + 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 = 0; i < ni - 1; ++ i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 0; -- i ) + { + double xm = grid->x[ i ]; + 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 = ni - 1; i >= 1; -- i ) + { + double xm = grid->x[ i ]; + 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 = this->x.size(); + std::cout << " DumpField x.size() = " << x.size() << "\n"; + //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.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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Post.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Post.h new file mode 100644 index 00000000..6ad0d3b6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Post.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +double compute_l2norm( int ni, std::vector & r ); +double compute_max_error( int ni, std::vector & u_error ); + +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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/README.txt b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/README.txt new file mode 100644 index 00000000..5a4410fb --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Solver.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Solver.cpp new file mode 100644 index 00000000..08828986 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Solver.cpp @@ -0,0 +1,536 @@ +#include "Solver.h" +#include "CgnsUtil.h" +#include "Parallel.h" +#include "Post.h" +#include "Weno.h" +#include "ZoneState.h" +#include "global.h" +#include +#include +#include +#include +#include +#include + +Solver::Solver() +{ + Parallel::Init(); + //this->nghost = 1; + //this->scheme = Scheme::FTCS; + //this->scheme = Scheme::RungeKutta; + //this->scheme = Scheme::CN; + //this->scheme = Scheme::ICP; + this->scheme = Scheme::WENO; + this->nghost = 3; + Global::nghost = this->nghost; +} + +Solver::~Solver() +{ + Parallel::Finalize(); +} + +void Solver::Run() +{ + this->ReadGrid(); + this->InitTopo(); + this->InitFields(); + this->SolveFields(); + //this->PostProcess(); +} + +void Solver::ReadGrid() +{ + std::string fileName = "../burgers1d4blocks.cgns"; + ReadCgnsGridBaseZone( fileName ); + ReadCgnsGrid( fileName ); +} + +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 = nullptr; + if ( scheme == Scheme::WENO ) { + field = new WenoField(); + } + else { + field = new FieldSub(); + } + 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::DumpInitialFields() +{ + this->PostProcess(); +} + +void Solver::SolveFields() +{ + this->DumpInitialFields(); + for ( int it = 0; it < Global::nt; ++ it ) + { + Global::iter = it; + switch (scheme) { + case Scheme::FTCS: + this->FTCS(); + break; + case Scheme::CN: + this->CN(); + break; + case Scheme::ICP: + this->ICP(); + break; + case Scheme::WENO: + this->RungeKutta(); + break; + case Scheme::RungeKutta: + this->RungeKutta(); + break; + default: + this->FTCS(); + } + if ( ( Global::iter + 1 ) % 250 == 0 ) + { + std::print( "it = {} nt = {}\n", Global::iter + 1, Global::nt ); + this->PostProcess(); + } + + } +} + +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::CN() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->CN( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::ICP() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Field * field = Global::fields[ iZone ]; + Zone * zone = Global::zones[ iZone ]; + zone->zoneIndex = iZone; + field->ICP( zone ); + } + this->Boundary(); + this->UpdateOldField(); +} + +void Solver::RungeKutta() +{ + for ( int istage = 0; istage < 3; ++ istage ) + { + this->RungeKutta( istage ); + } + this->UpdateOldField(); +} + +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(); +} + +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::UploadInterfaceField() +{ + for ( int iZone = 0; iZone < LocalZone::nZones; ++ iZone ) + { + Interface * interface = Global::interfaces[ iZone ]; + + Field * field = Global::fields[ iZone ]; + + int nsend_zones = interface->send_to_zones.size(); + for ( int iSend = 0; iSend < nsend_zones; ++ iSend ) + { + int zone_to_send = interface->send_to_zones[ iSend ]; + std::vector & donorfaces_for_send = interface->donorfaces_for_send[ iSend ]; + std::vector & donorijk_for_send = interface->donorijk_for_send[ iSend ]; + std::vector & donordata_for_send = interface->donordata_for_send[ iSend ]; + + int nInterFaces = donorfaces_for_send.size(); + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + int id_cell = donorijk_for_send[ ijkpos + ig ] - 1; + donordata_for_send[ data_pos + ig ] = field->u[ id_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 ]; + + int index_dim = 1; + + int ijkpos = index_dim * local_faceid * nghost; + int data_pos = local_faceid * nghost; + int donor_data_pos = i * nghost; + + for ( int ig = 0; ig < nghost; ++ ig ) + { + double donor_value = donordata[ donor_data_pos + ig ]; + donor_interface->data_recv[ data_pos + ig ] = 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->zoneList.size(); + + int index_dim = 1; + for ( int iFace = 0; iFace < nInterFaces; ++ iFace ) + { + int ijkpos = index_dim * iFace * nghost; + int data_pos = iFace * nghost; + for ( int ig = 0; ig < nghost; ++ ig ) + { + int ig_cell = interface->ijk_ghosts[ ijkpos + ig ] - 1; + + double donor_value = interface->data_recv[ data_pos + ig ]; + field->u[ ig_cell ] = donor_value; + } + } + } +} + +void Solver::ExchangeInterfaceField() +{ + this->UploadInterfaceField(); + this->UpdateInterfaceField(); + this->DownloadInterfaceField(); +} + +void Solver::PostProcess() +{ + std::string total_string = {}; + std::fstream file; + if ( Parallel::pid == Parallel::serverid ) + { + std::string filename = std::format( "field_final{}.csv", Global::iter+1 ); + file.open( filename.c_str(), std::fstream::out ); + } + for ( int iZone = 0; iZone < ZoneState::nZones; ++ iZone ) + { + int send_pid = ZoneState::pids[ iZone ]; + int recv_pid = Parallel::serverid; + + Global::file_string = {}; + + if ( Parallel::pid == send_pid ) + { + int local_zoneid = ZoneState::g2lzoneids[ iZone ]; + + Grid * grid = Global::grids[ local_zoneid ]; + Field * field = Global::fields[ local_zoneid ]; + field->PostProcess( grid ); + } + + HXSendRecvString( Global::file_string, send_pid, Parallel::serverid ); + + if ( Parallel::pid == Parallel::serverid ) + { + total_string += Global::file_string; + } + } + if ( Parallel::pid == Parallel::serverid ) + { + std::format_to( std::ostream_iterator( file ), "{}", total_string ); + file.close(); + } +} + +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 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, this->nghost ); + } + int nInterfaces = interface->zoneList.size(); + int nData = nInterfaces * Global::nghost; + interface->data_recv.resize( nData ); + interface->data_send.resize( nData ); + } + + 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(); +} \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Solver.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Solver.h new file mode 100644 index 00000000..ef1e13b4 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Solver.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include "Global.h" +#include "Grid.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, + CN, //Crank¨CNicolson + ICP, //Implicit Compact Pade (ICP) Scheme + WENO, + RungeKutta +}; + +class Solver +{ +public: + Solver(); + ~Solver(); +public: + Scheme scheme; + int nghost; +public: + void Run(); + void ReadGrid(); + void InitFields(); + void InitTopo(); + void SolveFields(); + void DumpInitialFields(); +public: + void Boundary(); + void UpdateOldField(); + void UploadInterfaceField(); + void UpdateInterfaceField(); + void DownloadInterfaceField(); + void ExchangeInterfaceField(); + void PrintField( std::vector & f ); +public: + void PostProcess(); +public: + void FTCS(); + void CN(); + void ICP(); + void RungeKutta(); + void RungeKutta( int istage ); +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Vec1d.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Vec1d.h new file mode 100644 index 00000000..ce6ed7c1 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Vec1d.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Vec1d +{ +public: + std::vector data; + int ist = 0; +public: + void Allocate( int ist, int ied, double value = 0 ) + { + int nelement = ied - ist + 1; + this->data.resize( nelement, value ); + this->ist = ist; + } + std::size_t size() + { + return this->data.size(); + } + + double operator [] ( int i ) const + { + return data[ i - ist ]; + } + + double & operator [] ( int i ) + { + return data[ i - ist ]; + } + + Vec1d & operator = ( const Vec1d & rhs ) + { + if ( this == & rhs ) return * this; + this->data = rhs.data; + + return * this; + } +}; diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Weno.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Weno.cpp new file mode 100644 index 00000000..e4f1c1ae --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Weno.cpp @@ -0,0 +1,330 @@ +#include "Weno.h" +#include "Global.h" +#include "Grid.h" +#include "cgnslib.h" +#include +#include +#include +#include +#include + +void WenoField::Init( Grid * grid ) +{ + this->ni = grid->x.size(); + Vec1d & x = grid->x; + this->dx = std::abs( x[ 1 ] - x[ 0 ] ); + this->dt = 0.0001; + this->total_time = 0.25; + this->nt = std::round( total_time / dt ); + this->ns = 10; + + std::print( "ni={}\n",ni ); + std::print( "ns={}\n", ns ); + std::print( "dt={}\n", dt ); + std::print( "total_time={}\n", total_time ); + std::print( "dx={}\n", dx ); + std::print( "nt={}\n", nt ); + std::cout << "this->dt = " << this->dt << "\n"; + std::cout << "this->total_time = " << this->total_time << "\n"; + std::cout << "this->nt = " << this->nt << "\n"; + std::cout << "this->ni = " << this->ni << "\n"; + std::cout << "nt * dt = " << nt * dt << "\n"; + + int freq = std::round( nt / ns ); + std::print( "freq = {}\n", freq ); + Global::nt = nt; + + int ighost = 3; + int ist = 0 - ighost; + int ied = this->ni - 1 + ighost; + + std::vector ulist( ns + 1 ); + + for ( int i = 0; i < ulist.size(); ++ i ) + { + ulist[ i ].Allocate( ist, ied, 0 ); + } + + un.Allocate( ist, ied, 0 ); // numerical solsution at every time step + u.Allocate( ist, ied, 0 ); // temporary array during RK3 integration + res.Allocate( 0, this->ni, 0 ); //N+1 + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = std::sin( 2.0 * std::numbers::pi * x[ i ] ); + } + + int kkk = 1; +} + +void WenoField::PhysicalBoundary( Zone * zone ) +{ + int nbccos = zone->bccos.size(); + for ( int ibcco = 0; ibcco < nbccos; ++ ibcco ) + { + ZoneBc * zonebc = zone->bccos[ ibcco ]; + Region region; + region.SetRegion( zonebc->pnts ); + Boundary( region, zonebc->bcType ); + } +} + +void WenoField::Boundary( Region ®ion, int bcType ) +{ + if ( bcType == BCInflow ) + { + this->InflowBc( region ); + } + else if ( bcType == BCExtrapolate || bcType == BCOutflow ) + { + this->OutflowBc( region ); + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 ib = i - 1; //index from 0 + int in = ib - idir; + + int ig1 = ib + idir; + int ig2 = ig1 + idir; + int ig3 = ig2 + idir; + + this->u[ ib ] = 0.0; + this->u[ ig1 ] = 2.0 * u[ ib ] - 1.0 * u[ in ]; + this->u[ ig2 ] = 3.0 * u[ ib ] - 2.0 * u[ in ]; + this->u[ ig3 ] = 4.0 * u[ ib ] - 3.0 * u[ in ]; + } +} + +void WenoField::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 WenoField::RungeKutta3Stage0( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = u[ i ] + dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage1( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = 0.75 * un[ i ] + 0.25 * u[ i ] + 0.25 * dt * res[ i ]; + } +} + +void WenoField::RungeKutta3Stage2( Zone * zone ) +{ + this->Rhs( this->u, this->res ); + + double c1 = 1.0 / 3.0; + double c2 = 2.0 / 3.0; + double c3 = 2.0 / 3.0; + + for ( int i = 0; i < ni; ++ i ) + { + u[ i ] = c1 * un[ i ] + c2 * u[ i ] + c3 * dt * res[ i ]; + } +} + +void WenoField::Rhs( Vec1d & u, Vec1d & res ) +{ + Vec1d uL; + uL.Allocate( 0, ni, 0 ); + + Vec1d uR; + uR.Allocate( 0, ni, 0 ); + + wenoL( ni, u, uL ); + wenoR( ni, u, uR ); + + for ( int i = 0; i < ni; ++ i ) + { + if ( u[ i ] >= 0.0 ) + { + res[ i ] = - u[ i ] * ( uL[ i + 1 ] - uL[ i ] ) / dx; + } + else + { + res[ i ] = - u[ i ] * ( uR[ i + 1 ] - uR[ i ] ) / dx; + } + } +} + +void WenoField::UpdateOldField() +{ + this->un = this->u; +} + +void WenoField::PostProcess( Grid * grid ) +{ + this->DumpField( grid->x, u ); +} + +void WenoField::DumpField( Vec1d & x, Vec1d & u ) +{ + for ( int i = 0; i < x.size(); ++ i ) + { + Global::file_string += std::format( "{:.16f} {:.16f}\n", x[ i ], u[ i ] ); + } +} + +double wcL( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 1.0e-1 / ( SQR( eps + s1 ) ); + double c2 = 6.0e-1 / ( SQR( eps + s2 ) ); + double c3 = 3.0e-1 / ( SQR( eps + s3 ) ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils + double q1 = v1 / 3.0 - 7.0 / 6.0 * v2 + 11.0 / 6.0 * v3; + double q2 = -v2 / 6.0 + 5.0 / 6.0 * v3 + v4 / 3.0; + double q3 = v3 / 3.0 + 5.0 / 6.0 * v4 - v5 / 6.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +double wcR( double v1, double v2, double v3, double v4, double v5 ) +{ + double eps = 1.0e-6; + + // smoothness indicators + double s1 = ( 13.0 / 12.0 ) * SQR( v1 - 2.0 * v2 + v3 ) + 0.25 * SQR( v1 - 4.0 * v2 + 3.0 * v3 ); + double s2 = ( 13.0 / 12.0 ) * SQR( v2 - 2.0 * v3 + v4 ) + 0.25 * SQR( v2 - v4 ); + double s3 = ( 13.0 / 12.0 ) * SQR( v3 - 2.0 * v4 + v5 ) + 0.25 * SQR( 3.0 * v3 - 4.0 * v4 + v5 ); + + // computing nonlinear weights w1, w2, w3 + double c1 = 3.0e-1 / SQR( eps + s1 ); + double c2 = 6.0e-1 / SQR( eps + s2 ); + double c3 = 1.0e-1 / SQR( eps + s3 ); + + double w1 = c1 / ( c1 + c2 + c3 ); + double w2 = c2 / ( c1 + c2 + c3 ); + double w3 = c3 / ( c1 + c2 + c3 ); + + // candiate stencils; + double q1 = -v1 / 6.0 + 5.0 / 6.0 * v2 + v3 / 3.0; + double q2 = v2 / 3.0 + 5.0 / 6.0 * v3 - v4 / 6.0; + double q3 = 11.0 / 6.0 * v3 - 7.0 / 6.0 * v4 + v5 / 3.0; + + // reconstructed value at interface + double f = ( w1 * q1 + w2 * q2 + w3 * q3 ); + + return f; +} + +//----------------------------------------------------------------------------- +// WENO reconstruction for upwind direction (positive; left to right) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i+1/2; j = 1,...,N +//----------------------------------------------------------------------------- +void wenoL( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 2 ]; + double v2 = u[ ii - 1 ]; + double v3 = u[ ii ]; + double v4 = u[ ii + 1 ]; + double v5 = u[ ii + 2 ]; + f[ i ] = wcL( v1, v2, v3, v4, v5 ); + } +} + +//----------------------------------------------------------------------------- +// CRWENO reconstruction for downwind direction (negative; right to left) +// u(i): solution values at finite difference grid nodes i = 1,...,N+1 +// f(j): reconstructed values at nodes j = i-1/2; j = 2,...,N+1 +//----------------------------------------------------------------------------- +void wenoR( int N, Vec1d & u, Vec1d & f ) +{ + for ( int i = 0; i <= N; ++ i ) + { + int ii = i - 1; + double v1 = u[ ii - 1 ]; + double v2 = u[ ii ]; + double v3 = u[ ii + 1 ]; + double v4 = u[ ii + 2 ]; + double v5 = u[ ii + 3 ]; + f[ i ] = wcR( v1, v2, v3, v4, v5 ); + } +} + diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Weno.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Weno.h new file mode 100644 index 00000000..60dbf194 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/Weno.h @@ -0,0 +1,40 @@ +#pragma once +#include "Vec1d.h" +#include "Field.h" +#include + +template +auto SQR(Args... args) { + return ( ... + ( args * args ) ); +} + +class WenoField : public Field +{ +public: + int ni; + int nt; + double dx, dt, total_time; + int ns; +public: + void Init( Grid * grid ); +public: + void PhysicalBoundary( Zone * zone ); + void Boundary( Region & region, int bcType ); + void InflowBc( Region & region ); + void OutflowBc( Region & region ); +public: + void RungeKutta( Zone * zone, int istage ); + void RungeKutta3Stage0( Zone * zone ); + void RungeKutta3Stage1( Zone * zone ); + void RungeKutta3Stage2( Zone * zone ); + void Rhs( Vec1d & u, Vec1d & res ); +public: + void UpdateOldField(); + void PostProcess( Grid * grid ); + void DumpField( Vec1d & x, Vec1d & u ); +}; + +double wcL( double v1, double v2, double v3, double v4, double v5 ); +double wcR( double v1, double v2, double v3, double v4, double v5 ); +void wenoL( int N, Vec1d & u, Vec1d & f ); +void wenoR( int N, Vec1d & u, Vec1d & f ); diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/WenoPlot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/WenoPlot.py new file mode 100644 index 00000000..84340f68 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/WenoPlot.py @@ -0,0 +1,49 @@ +import numpy as np +import matplotlib.pyplot as plt +import csv + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + headers = next(readCSV) + num_columns = len(headers) + print(f'num_columns = {num_columns}') + icount = 0 + for row in readCSV: + icount += 1 + +ni = icount + 1 +print("ni=",ni) + +ns = num_columns - 2 + +u = np.zeros( (ni, ns + 1 ) ) +x = np.zeros( (ni) ) + +with open('field_final.csv', newline='') as csvfile: + readCSV = csv.reader(csvfile, delimiter= ' ') + i = 0 + for row in readCSV: + #print(f"row={row}\n") + x[i] = float(row[0]) + for j in range(1,num_columns): + u[i][j-1] = float(row[j]) + i += 1 + + +print("u.shape=",u.shape) +n1 = u.shape[0] +n2 = u.shape[1] +print(f"n1={n1},n2={n2}") + +#x = np.linspace(0,1, num=ni) + +tm = 0.25 + +plt.figure("OneFLOW-CFD Solver", figsize=(6, 4), dpi=100) +for k in range(0, ns+1): + plt.plot(x, u[:,k], linewidth=1.0, label="t="+format(tm*k/ns, ".4f")) +plt.xlabel("$x$") +plt.ylabel("$u$") +plt.title("Inviscid Burgers Equation: Non-Conservative Form-WENO-5 Scheme") +plt.legend(loc='upper right', fontsize='6') +plt.show() \ No newline at end of file diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/ZoneState.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/ZoneState.cpp new file mode 100644 index 00000000..ff810849 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/ZoneState.h b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/ZoneState.h new file mode 100644 index 00000000..1096d632 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/burgers1d4blocks.cgns b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/burgers1d4blocks.cgns new file mode 100644 index 00000000..3585da45 Binary files /dev/null and b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/burgers1d4blocks.cgns differ diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/main.cpp b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/main.cpp new file mode 100644 index 00000000..fcce6376 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/plot.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/plot.py new file mode 100644 index 00000000..41a173a6 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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="ICP 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/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/plotting2.jl b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/01a/plotting2.jl new file mode 100644 index 00000000..c74255b2 --- /dev/null +++ b/example/inviscid-burgers-equation/non-conservative-form/weno5/cpp/parallel/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/inviscid-burgers-equation/non-conservative-form/weno5/01/weno5.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/python/01/weno5.py similarity index 100% rename from example/inviscid-burgers-equation/non-conservative-form/weno5/01/weno5.py rename to example/inviscid-burgers-equation/non-conservative-form/weno5/python/01/weno5.py diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/02/weno5.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/python/02/weno5.py similarity index 100% rename from example/inviscid-burgers-equation/non-conservative-form/weno5/02/weno5.py rename to example/inviscid-burgers-equation/non-conservative-form/weno5/python/02/weno5.py diff --git a/example/inviscid-burgers-equation/non-conservative-form/weno5/03/weno5.py b/example/inviscid-burgers-equation/non-conservative-form/weno5/python/03/weno5.py similarity index 100% rename from example/inviscid-burgers-equation/non-conservative-form/weno5/03/weno5.py rename to example/inviscid-burgers-equation/non-conservative-form/weno5/python/03/weno5.py diff --git a/example/numerical/matrix/gauss-elimination/01/CMakeLists.txt b/example/numerical/matrix/gauss-elimination/01/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/matrix/gauss-elimination/01/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/matrix/gauss-elimination/01/main.cpp b/example/numerical/matrix/gauss-elimination/01/main.cpp new file mode 100644 index 00000000..3cb53dca --- /dev/null +++ b/example/numerical/matrix/gauss-elimination/01/main.cpp @@ -0,0 +1,129 @@ +#include +#include +#include +#include + +void Print( std::vector & x ); +void Print( std::vector> & a ); +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ); +void gaussElimination( std::vector> & a, std::vector & b ); + +void Print( std::vector & x ) +{ + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + +void gaussElimination( std::vector> & a, std::vector & b ) +{ + int n = a.size(); + + // ÏûÔª¹ý³Ì + for ( int i = 0; i < n; ++i ) { + // ÕÒµ½µ±Ç°ÁеÄ×î´óÖµ + double maxVal = std::abs( a[ i ][ i ] ); + int maxRow = i; + for ( int k = i + 1; k < n; k++ ) + { + if ( std::abs( a[ k ][ i ] ) > maxVal ) + { + maxVal = std::abs( a[ k ][ i ] ); + maxRow = k; + } + } + std::swap( a[ i ], a[ maxRow ] ); + std::swap( b[ i ], b[ maxRow ] ); + + // ½øÐÐÏûÔª + for ( int j = i + 1; j < n; j++ ) + { + double factor = a[ j ][ i ] / a[ i ][ i ]; + for ( int k = i; k < n; k++ ) + { + a[ j ][ k ] -= factor * a[ i ][ k ]; + } + b[ j ] -= factor * b[ i ]; + } + } + + // »Ø´ú¹ý³Ì + std::vector x( n ); + for ( int i = n - 1; i >= 0; i-- ) + { + x[ i ] = b[ i ]; + for ( int j = i + 1; j < n; j++ ) + { + x[ i ] -= a[ i ][ j ] * x[ j ]; + } + x[ i ] /= a[ i ][ i ]; + } + + // Êä³ö½á¹û + for ( int i = 0; i < n; ++ i ) + { + std::print( "b{} = {:12.6f}\n", i + 1, b[ i ] ); + } + + // Êä³ö½á¹û + for ( int i = 0; i < n; ++ i ) + { + std::print( "x{} = {:12.6f}\n", i + 1, x[ i ] ); + } +} + +int main() +{ + std::vector>a{ + {3.0, 2.0,-4.0}, + {2.0, 3.0, 3.0}, + {5.0, -3, 1.0} + }; + + Print( a ); + + //std::print( "a.size()={}\n", a.size() ); + std::vector b{ 3.0,15.0,14.0 }; + std::vector xx{ 3.0,1.0,2.0 }; + std::vector y( xx.size() ); + + MatrixMultiply( a, xx, y ); + + gaussElimination( a, b ); + + Print( a ); + + Print( y ); + + return 0; +} + diff --git a/example/numerical/matrix/gauss-elimination/01a/CMakeLists.txt b/example/numerical/matrix/gauss-elimination/01a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/matrix/gauss-elimination/01a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/matrix/gauss-elimination/01a/main.cpp b/example/numerical/matrix/gauss-elimination/01a/main.cpp new file mode 100644 index 00000000..5486ca69 --- /dev/null +++ b/example/numerical/matrix/gauss-elimination/01a/main.cpp @@ -0,0 +1,127 @@ +#include +#include + +void Print( std::vector & x ); +void Print( std::vector> & a ); +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ); +void gaussElimination( std::vector> & a, std::vector & b ); + +void Print( std::vector & x ) +{ + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + +void gaussElimination( std::vector> & a, std::vector & b ) +{ + int n = a.size(); + + // ÏûÔª¹ý³Ì + for ( int i = 0; i < n; ++ i ) { + // ÕÒµ½µ±Ç°ÁеÄ×î´óÖµ + double maxVal = std::abs( a[ i ][ i ] ); + int maxRow = i; + for ( int k = i + 1; k < n; ++ k ) + { + if ( std::abs( a[ k ][ i ] ) > maxVal ) + { + maxVal = std::abs( a[ k ][ i ] ); + maxRow = k; + } + } + std::swap( a[ i ], a[ maxRow ] ); + std::swap( b[ i ], b[ maxRow ] ); + + // ½øÐÐÏûÔª + for ( int j = i + 1; j < n; ++ j ) + { + double factor = a[ j ][ i ] / a[ i ][ i ]; + for ( int k = i; k < n; ++ k ) + { + a[ j ][ k ] -= factor * a[ i ][ k ]; + } + b[ j ] -= factor * b[ i ]; + } + } + + // »Ø´ú¹ý³Ì + std::vector x( n ); + for ( int i = n - 1; i >= 0; -- i ) + { + x[ i ] = b[ i ]; + for ( int j = i + 1; j < n; ++ j ) + { + x[ i ] -= a[ i ][ j ] * x[ j ]; + } + x[ i ] /= a[ i ][ i ]; + } + + // Êä³ö½á¹û + for ( int i = 0; i < n; ++ i ) + { + std::print( "b{} = {:12.6f}\n", i + 1, b[ i ] ); + } + + // Êä³ö½á¹û + for ( int i = 0; i < n; ++ i ) + { + std::print( "x{} = {:12.6f}\n", i + 1, x[ i ] ); + } +} + +int main() +{ + std::vector>a{ + {3.0, 2.0,-4.0}, + {2.0, 3.0, 3.0}, + {5.0, -3, 1.0} + }; + + Print( a ); + + //std::print( "a.size()={}\n", a.size() ); + std::vector b{ 3.0,15.0,14.0 }; + std::vector xx{ 3.0,1.0,2.0 }; + std::vector y( xx.size() ); + + MatrixMultiply( a, xx, y ); + + gaussElimination( a, b ); + + Print( a ); + + Print( y ); + + return 0; +} + diff --git a/example/numerical/matrix/upper-triangular/01/CMakeLists.txt b/example/numerical/matrix/upper-triangular/01/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/matrix/upper-triangular/01/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/matrix/upper-triangular/01/main.cpp b/example/numerical/matrix/upper-triangular/01/main.cpp new file mode 100644 index 00000000..e774969d --- /dev/null +++ b/example/numerical/matrix/upper-triangular/01/main.cpp @@ -0,0 +1,25 @@ +import std; + +void upper_triangular_matrix( const std::vector> & a ) +{ +} + +int main( int argc, char ** argv ) +{ + std::vector>u{ + {10,11,12}, + {0,20,21}, + {0,0,30} + }; + int N = u.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{} ", u[ i ][ j ] ); + } + std::println(); + } + + return 0; +} diff --git a/example/numerical/matrix/upper-triangular/01a/CMakeLists.txt b/example/numerical/matrix/upper-triangular/01a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/matrix/upper-triangular/01a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/matrix/upper-triangular/01a/main.cpp b/example/numerical/matrix/upper-triangular/01a/main.cpp new file mode 100644 index 00000000..e774969d --- /dev/null +++ b/example/numerical/matrix/upper-triangular/01a/main.cpp @@ -0,0 +1,25 @@ +import std; + +void upper_triangular_matrix( const std::vector> & a ) +{ +} + +int main( int argc, char ** argv ) +{ + std::vector>u{ + {10,11,12}, + {0,20,21}, + {0,0,30} + }; + int N = u.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{} ", u[ i ][ j ] ); + } + std::println(); + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/01/CMakeLists.txt b/example/numerical/tdma/cpp/01/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01/main.cpp b/example/numerical/tdma/cpp/01/main.cpp new file mode 100644 index 00000000..30a6d7cc --- /dev/null +++ b/example/numerical/tdma/cpp/01/main.cpp @@ -0,0 +1,47 @@ +import std; + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + std::vector a{ 0, -1, -1, -1, -1 }; // ϶ԽÇÏß + std::vector b{ 2, 2, 2, 2, 2 }; // Ö÷¶Ô½ÇÏß + std::vector c{ -1, -1, -1, -1, 0 }; // É϶ԽÇÏß + std::vector d{ 1.0, 1.0, 1.0, 1.0, 1.0 }; // Óұߵij£ÊýÏòÁ¿ + std::vector x( d.size() ); // ½á¹ûÏòÁ¿ + + thomas_algorithm( a, b, c, d, x ); + for ( auto v : x ) + { + std::print( "{} ", v ); + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/01a/CMakeLists.txt b/example/numerical/tdma/cpp/01a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01a/main.cpp b/example/numerical/tdma/cpp/01a/main.cpp new file mode 100644 index 00000000..bcf4219c --- /dev/null +++ b/example/numerical/tdma/cpp/01a/main.cpp @@ -0,0 +1,55 @@ +import std; + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + const int N = 4; + + std::vector a( N, -1 ); + std::vector b( N, 2 ); + std::vector c( N, -1 ); + std::vector d( N, 0.0 ); + a[ 0 ] = 0; + c[ N - 1 ] = 0; + d[ 0 ] = 1; + d[ N - 1 ] = 1; + + std::vector x( d.size() ); + + thomas_algorithm( a, b, c, d, x ); + + for ( auto v : x ) + { + std::print( "{} ", v ); + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/01a0/CMakeLists.txt b/example/numerical/tdma/cpp/01a0/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01a0/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01a0/main.cpp b/example/numerical/tdma/cpp/01a0/main.cpp new file mode 100644 index 00000000..4788e9aa --- /dev/null +++ b/example/numerical/tdma/cpp/01a0/main.cpp @@ -0,0 +1,76 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + const int N = 4; + + for ( int N = 4; N >= 1; --N ) + { + int totalN = N + 2; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 0.0 ); + a[ 0 ] = 0; + a[ 1 ] = 0; + b[ 0 ] = 1; + b[ N + 1 ] = 1; + c[ N ] = 0; + c[ N + 1 ] = 0; + y[ 0 ] = 0; + y[ 1 ] = 1; + y[ N ] = 1; + y[ N + 1 ] = 0; + + std::vector anew( a.begin() + 1, a.end() - 1 ); + std::vector bnew( b.begin() + 1, b.end() - 1 ); + std::vector cnew( c.begin() + 1, c.end() - 1 ); + std::vector ynew( y.begin() + 1, y.end() - 1 ); + std::vector x( ynew.size() ); + + thomas_algorithm( anew, bnew, cnew, ynew, x ); + std::print( "N={}\n", N ); + Print( x, "x" ); + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/01a1/CMakeLists.txt b/example/numerical/tdma/cpp/01a1/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01a1/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01a1/main.cpp b/example/numerical/tdma/cpp/01a1/main.cpp new file mode 100644 index 00000000..3b2cd1c2 --- /dev/null +++ b/example/numerical/tdma/cpp/01a1/main.cpp @@ -0,0 +1,124 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + for ( int N = 4; N >= 1; --N ) + { + int totalN = N + 2; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 0.0 ); + a[ 0 ] = 0; + a[ 1 ] = 0; + b[ 0 ] = 1; + b[ N + 1 ] = 1; + c[ N ] = 0; + c[ N + 1 ] = 0; + y[ 0 ] = 0; + y[ 1 ] = 1; + y[ N ] = 1; + y[ N + 1 ] = 0; + + std::vector anew( a.begin() + 1, a.end() - 1 ); + std::vector bnew( b.begin() + 1, b.end() - 1 ); + std::vector cnew( c.begin() + 1, c.end() - 1 ); + std::vector ynew( y.begin() + 1, y.end() - 1 ); + std::vector x( ynew.size() ); + + thomas_algorithm( anew, bnew, cnew, ynew, x ); + std::print( "N={}\n", N ); + Print( x, "x" ); + } + { + int N = 8; + double lv = std::log2( 8 ); + int M = log2( N + 1 ) - 1; + std::print( "M={}\n", M ); + int offset = 1; + int joffset = 2; + int start = 0; + for ( int i = 0; i <= M; ++ i ) + { + int jstart = joffset - 1; + std::print( "i={}\n", i ); + std::print( "jstart={},N-1={}\n", jstart, N - 1 ); + + std::print( "j=" ); + + for ( int j = jstart; j <= N - 1; j += joffset ) + { + int id1 = j - offset; + int id2 = j + offset; + std::print( "{} ", j ); + } + std::print( "\n" ); + + std::print( "id1=" ); + + for ( int j = jstart; j <= N - 1; j += joffset ) + { + int id1 = j - offset; + int id2 = j + offset; + std::print( "{} ", id1 ); + } + std::print( "\n" ); + + std::print( "id2=" ); + + for ( int j = jstart; j <= N - 1; j += joffset ) + { + int id1 = j - offset; + int id2 = j + offset; + std::print( "{} ", id2 ); + } + std::print( "\n" ); + + offset *= 2; + joffset *= 2; + } + int kkk = 1; + + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/01b/CMakeLists.txt b/example/numerical/tdma/cpp/01b/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01b/main.cpp b/example/numerical/tdma/cpp/01b/main.cpp new file mode 100644 index 00000000..53b21f7a --- /dev/null +++ b/example/numerical/tdma/cpp/01b/main.cpp @@ -0,0 +1,130 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void split( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a_bar, + std::vector & b_bar, + std::vector & c_bar, + std::vector & y_bar ) +{ + int N = a.size(); + a_bar.resize( N ); + b_bar.resize( N ); + c_bar.resize( N ); + y_bar.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + double bim1 = 0; + double bip1 = 0; + double aim1 = 0; + double aip1 = 0; + double cim1 = 0; + double cip1 = 0; + double yim1 = 0; + double yip1 = 0; + double alpha = 0; + double beta = 0; + if ( i != 0 ) + { + aim1 = a[ i - 1 ]; + bim1 = b[ i - 1 ]; + cim1 = c[ i - 1 ]; + yim1 = y[ i - 1 ]; + alpha = - a[ i ] / bim1; + } + + if ( i != N - 1 ) + { + aip1 = a[ i + 1 ]; + bip1 = b[ i + 1 ]; + cip1 = c[ i + 1 ]; + yip1 = y[ i + 1 ]; + beta = - c[ i ] / bip1; + } + a_bar[ i ] = alpha * aim1; + c_bar[ i ] = beta * cip1; + b_bar[ i ] = b[ i ] + alpha * cim1 + beta * aip1; + y_bar[ i ] = y[ i ] + alpha * yim1 + beta * yip1; + } +} + +int main( int argc, char ** argv ) +{ + const int N = 4; + + std::vector a( N, -1 ); + std::vector b( N, 2 ); + std::vector c( N, -1 ); + std::vector d( N, 0.0 ); + a[ 0 ] = 0; + c[ N - 1 ] = 0; + d[ 0 ] = 1; + d[ N - 1 ] = 1; + + std::vector x( d.size() ); + + std::vector as, bs, cs, ds; + split( a, b, c, d, as, bs, cs, ds ); + + Print( a, "a" ); + Print( b, "b" ); + Print( c, "c" ); + Print( d, "d" ); + + Print( as, "as" ); + Print( bs, "bs" ); + Print( cs, "cs" ); + Print( ds, "ds" ); + + //thomas_algorithm( a, b, c, d, x ); + + //for ( auto v : x ) + //{ + // std::print( "{} ", v ); + //} + + return 0; +} diff --git a/example/numerical/tdma/cpp/01c/CMakeLists.txt b/example/numerical/tdma/cpp/01c/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01c/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01c/main.cpp b/example/numerical/tdma/cpp/01c/main.cpp new file mode 100644 index 00000000..e12bb1a8 --- /dev/null +++ b/example/numerical/tdma/cpp/01c/main.cpp @@ -0,0 +1,179 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void split( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a_bar, + std::vector & b_bar, + std::vector & c_bar, + std::vector & y_bar ) +{ + int N = a.size(); + a_bar.resize( N ); + b_bar.resize( N ); + c_bar.resize( N ); + y_bar.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + double bim1 = 0; + double bip1 = 0; + double aim1 = 0; + double aip1 = 0; + double cim1 = 0; + double cip1 = 0; + double yim1 = 0; + double yip1 = 0; + double alpha = 0; + double beta = 0; + if ( i != 0 ) + { + aim1 = a[ i - 1 ]; + bim1 = b[ i - 1 ]; + cim1 = c[ i - 1 ]; + yim1 = y[ i - 1 ]; + alpha = - a[ i ] / bim1; + } + + if ( i != N - 1 ) + { + aip1 = a[ i + 1 ]; + bip1 = b[ i + 1 ]; + cip1 = c[ i + 1 ]; + yip1 = y[ i + 1 ]; + beta = - c[ i ] / bip1; + } + a_bar[ i ] = alpha * aim1; + c_bar[ i ] = beta * cip1; + b_bar[ i ] = b[ i ] + alpha * cim1 + beta * aip1; + y_bar[ i ] = y[ i ] + alpha * yim1 + beta * yip1; + } +} + +void SetCyclicReductionValue +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int N = a.size(); + int halfN = N / 2; + a1.resize( halfN ); + b1.resize( halfN ); + c1.resize( halfN ); + y1.resize( halfN ); + a2.resize( halfN ); + b2.resize( halfN ); + c2.resize( halfN ); + y2.resize( halfN ); + for ( int i = 0; i < halfN; ++ i ) + { + int ieven = 2 * i; + int iodd = ieven + 1; + a1[ i ] = a[ ieven ]; + b1[ i ] = b[ ieven ]; + c1[ i ] = c[ ieven ]; + y1[ i ] = y[ ieven ]; + + a2[ i ] = a[ iodd ]; + b2[ i ] = b[ iodd ]; + c2[ i ] = c[ iodd ]; + y2[ i ] = y[ iodd ]; + } +} + +int main( int argc, char ** argv ) +{ + const int N = 8; + + std::vector a( N, -1 ); + std::vector b( N, 2 ); + std::vector c( N, -1 ); + std::vector y( N, 0.0 ); + a[ 0 ] = 0; + c[ N - 1 ] = 0; + y[ 0 ] = 1; + y[ N - 1 ] = 1; + + std::vector x( y.size() ); + + std::vector as, bs, cs, ys; + split( a, b, c, y, as, bs, cs, ys ); + + std::vector a1, b1, c1, y1; + std::vector a2, b2, c2, y2; + + SetCyclicReductionValue( as, bs, cs, ys, a1, b1, c1, y1, a2, b2, c2, y2 ); + + std::vector x1( y1.size() ); + std::vector x2( y2.size() ); + std::vector xx; + + thomas_algorithm( a, b, c, y, x ); + thomas_algorithm( a1, b1, c1, y1, x1 ); + thomas_algorithm( a2, b2, c2, y2, x2 ); + Print( x, "x" ); + Print( x1, "x1" ); + Print( x2, "x2" ); + + for ( int i = 0; i < x1.size(); ++ i ) + { + xx.push_back( x1[ i ] ); + xx.push_back( x2[ i ] ); + } + + Print( xx, "xx" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/01d/CMakeLists.txt b/example/numerical/tdma/cpp/01d/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01d/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01d/main.cpp b/example/numerical/tdma/cpp/01d/main.cpp new file mode 100644 index 00000000..e12bb1a8 --- /dev/null +++ b/example/numerical/tdma/cpp/01d/main.cpp @@ -0,0 +1,179 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void split( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a_bar, + std::vector & b_bar, + std::vector & c_bar, + std::vector & y_bar ) +{ + int N = a.size(); + a_bar.resize( N ); + b_bar.resize( N ); + c_bar.resize( N ); + y_bar.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + double bim1 = 0; + double bip1 = 0; + double aim1 = 0; + double aip1 = 0; + double cim1 = 0; + double cip1 = 0; + double yim1 = 0; + double yip1 = 0; + double alpha = 0; + double beta = 0; + if ( i != 0 ) + { + aim1 = a[ i - 1 ]; + bim1 = b[ i - 1 ]; + cim1 = c[ i - 1 ]; + yim1 = y[ i - 1 ]; + alpha = - a[ i ] / bim1; + } + + if ( i != N - 1 ) + { + aip1 = a[ i + 1 ]; + bip1 = b[ i + 1 ]; + cip1 = c[ i + 1 ]; + yip1 = y[ i + 1 ]; + beta = - c[ i ] / bip1; + } + a_bar[ i ] = alpha * aim1; + c_bar[ i ] = beta * cip1; + b_bar[ i ] = b[ i ] + alpha * cim1 + beta * aip1; + y_bar[ i ] = y[ i ] + alpha * yim1 + beta * yip1; + } +} + +void SetCyclicReductionValue +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int N = a.size(); + int halfN = N / 2; + a1.resize( halfN ); + b1.resize( halfN ); + c1.resize( halfN ); + y1.resize( halfN ); + a2.resize( halfN ); + b2.resize( halfN ); + c2.resize( halfN ); + y2.resize( halfN ); + for ( int i = 0; i < halfN; ++ i ) + { + int ieven = 2 * i; + int iodd = ieven + 1; + a1[ i ] = a[ ieven ]; + b1[ i ] = b[ ieven ]; + c1[ i ] = c[ ieven ]; + y1[ i ] = y[ ieven ]; + + a2[ i ] = a[ iodd ]; + b2[ i ] = b[ iodd ]; + c2[ i ] = c[ iodd ]; + y2[ i ] = y[ iodd ]; + } +} + +int main( int argc, char ** argv ) +{ + const int N = 8; + + std::vector a( N, -1 ); + std::vector b( N, 2 ); + std::vector c( N, -1 ); + std::vector y( N, 0.0 ); + a[ 0 ] = 0; + c[ N - 1 ] = 0; + y[ 0 ] = 1; + y[ N - 1 ] = 1; + + std::vector x( y.size() ); + + std::vector as, bs, cs, ys; + split( a, b, c, y, as, bs, cs, ys ); + + std::vector a1, b1, c1, y1; + std::vector a2, b2, c2, y2; + + SetCyclicReductionValue( as, bs, cs, ys, a1, b1, c1, y1, a2, b2, c2, y2 ); + + std::vector x1( y1.size() ); + std::vector x2( y2.size() ); + std::vector xx; + + thomas_algorithm( a, b, c, y, x ); + thomas_algorithm( a1, b1, c1, y1, x1 ); + thomas_algorithm( a2, b2, c2, y2, x2 ); + Print( x, "x" ); + Print( x1, "x1" ); + Print( x2, "x2" ); + + for ( int i = 0; i < x1.size(); ++ i ) + { + xx.push_back( x1[ i ] ); + xx.push_back( x2[ i ] ); + } + + Print( xx, "xx" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/01e/CMakeLists.txt b/example/numerical/tdma/cpp/01e/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01e/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01e/main.cpp b/example/numerical/tdma/cpp/01e/main.cpp new file mode 100644 index 00000000..06c6e283 --- /dev/null +++ b/example/numerical/tdma/cpp/01e/main.cpp @@ -0,0 +1,301 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void split( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a_bar, + std::vector & b_bar, + std::vector & c_bar, + std::vector & y_bar ) +{ + int N = a.size(); + a_bar.resize( N ); + b_bar.resize( N ); + c_bar.resize( N ); + y_bar.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + double bim1 = 0; + double bip1 = 0; + double aim1 = 0; + double aip1 = 0; + double cim1 = 0; + double cip1 = 0; + double yim1 = 0; + double yip1 = 0; + double alpha = 0; + double beta = 0; + if ( i != 0 ) + { + aim1 = a[ i - 1 ]; + bim1 = b[ i - 1 ]; + cim1 = c[ i - 1 ]; + yim1 = y[ i - 1 ]; + alpha = - a[ i ] / bim1; + } + + if ( i != N - 1 ) + { + aip1 = a[ i + 1 ]; + bip1 = b[ i + 1 ]; + cip1 = c[ i + 1 ]; + yip1 = y[ i + 1 ]; + beta = - c[ i ] / bip1; + } + a_bar[ i ] = alpha * aim1; + c_bar[ i ] = beta * cip1; + b_bar[ i ] = b[ i ] + alpha * cim1 + beta * aip1; + y_bar[ i ] = y[ i ] + alpha * yim1 + beta * yip1; + } +} + +void Boundary( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y ) +{ + int totalN = a.size(); + int N = totalN - 2; + a[ 0 ] = 0; + a[ 1 ] = 0; + b[ 0 ] = 1; + b[ N + 1 ] = 1; + c[ N ] = 0; + c[ N + 1 ] = 0; + y[ 0 ] = 0; + y[ N + 1 ] = 0; +} + +void SetCyclicReductionValue +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int N = a.size(); + int halfN = N / 2; + a1.resize( halfN ); + b1.resize( halfN ); + c1.resize( halfN ); + y1.resize( halfN ); + a2.resize( halfN ); + b2.resize( halfN ); + c2.resize( halfN ); + y2.resize( halfN ); + for ( int i = 0; i < halfN; ++ i ) + { + int ieven = 2 * i; + int iodd = ieven + 1; + a1[ i ] = a[ ieven ]; + b1[ i ] = b[ ieven ]; + c1[ i ] = c[ ieven ]; + y1[ i ] = y[ ieven ]; + + a2[ i ] = a[ iodd ]; + b2[ i ] = b[ iodd ]; + c2[ i ] = c[ iodd ]; + y2[ i ] = y[ iodd ]; + } +} + +void CyclicReduction( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & abar, + std::vector & bbar, + std::vector & cbar, + std::vector & ybar + ) +{ + int totalN = a.size(); + int N = totalN - 2; + for ( int i = 1; i <= N; ++ i ) + { + int in = std::max( 0, i - 1 ); + int ip = std::min( N + 1, i + 1 ); + + double alpha = - a[ i ] / b[ in ]; + double beta = - c[ i ] / b[ ip ]; + + abar[ i ] = alpha * a[ in ]; + cbar[ i ] = beta * c[ ip ]; + bbar[ i ] = b[ i ] + alpha * c[ in ] + beta * a[ ip ]; + ybar[ i ] = y[ i ] + alpha * y[ in ] + beta * y[ ip ]; + } +} + +void CR +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int totalN = a.size(); + int N = totalN - 2; + int halfN = N / 2; + int totalHalfN = halfN + 2; + a1.resize( totalHalfN ); + b1.resize( totalHalfN ); + c1.resize( totalHalfN ); + y1.resize( totalHalfN ); + + a2.resize( totalHalfN ); + b2.resize( totalHalfN ); + c2.resize( totalHalfN ); + y2.resize( totalHalfN ); + for ( int i = 1; i <= halfN; ++ i ) + { + int iodd = 2 * i - 1; + int ieven = iodd + 1; + + a1[ i ] = a[ iodd ]; + b1[ i ] = b[ iodd ]; + c1[ i ] = c[ iodd ]; + y1[ i ] = y[ iodd ]; + + a2[ i ] = a[ ieven ]; + b2[ i ] = b[ ieven ]; + c2[ i ] = c[ ieven ]; + y2[ i ] = y[ ieven ]; + } +} + +void Create( std::vector & a, std::vector & aNew ) +{ + aNew.assign( a.begin() + 1, a.end() - 1 ); +} + +int main( int argc, char ** argv ) +{ + const int N = 8; + + int totalN = N + 2; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 0.0 ); + y[ 1 ] = 1; + y[ N ] = 1; + + std::vector anew; + std::vector bnew; + std::vector cnew; + std::vector ynew; + std::vector x; + + Create( a, anew ); + Create( b, bnew ); + Create( c, cnew ); + Create( y, ynew ); + x.resize( ynew.size() ); + + thomas_algorithm( anew, bnew, cnew, ynew, x ); + Print( x, "x" ); + + Boundary( a, b, c, y ); + + std::vector acr( a.size() ); + std::vector bcr( b.size() ); + std::vector ccr( c.size() ); + std::vector ycr( y.size() ); + + CyclicReduction( a, b, c, y, acr, bcr, ccr, ycr ); + + std::vector a1, b1, c1, y1; + std::vector a2, b2, c2, y2; + + CR( acr, bcr, ccr, ycr, a1, b1, c1, y1, a2, b2, c2, y2 ); + + std::vector a1new,b1new,c1new,y1new; + std::vector a2new,b2new,c2new,y2new; + Create( a1, a1new ); + Create( b1, b1new ); + Create( c1, c1new ); + Create( y1, y1new ); + + Create( a2, a2new ); + Create( b2, b2new ); + Create( c2, c2new ); + Create( y2, y2new ); + std::vector x1( y1new.size() ); + std::vector x2( y2new.size() ); + std::vector xx; + + thomas_algorithm( a1new, b1new, c1new, y1new, x1 ); + thomas_algorithm( a2new, b2new, c2new, y2new, x2 ); + Print( x1, "x1" ); + Print( x2, "x2" ); + + for ( int i = 0; i < x1.size(); ++ i ) + { + xx.push_back( x1[ i ] ); + xx.push_back( x2[ i ] ); + } + + Print( xx, "xx" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/01f/CMakeLists.txt b/example/numerical/tdma/cpp/01f/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01f/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01f/main.cpp b/example/numerical/tdma/cpp/01f/main.cpp new file mode 100644 index 00000000..f5d425f9 --- /dev/null +++ b/example/numerical/tdma/cpp/01f/main.cpp @@ -0,0 +1,273 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void Boundary( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y ) +{ + int totalN = a.size(); + int N = totalN - 2; + a[ 0 ] = 0; + a[ 1 ] = 0; + b[ 0 ] = 1; + b[ N + 1 ] = 1; + c[ N ] = 0; + c[ N + 1 ] = 0; + y[ 0 ] = 0; + y[ N + 1 ] = 0; +} + +void SetCyclicReductionValue +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int N = a.size(); + int halfN = N / 2; + a1.resize( halfN ); + b1.resize( halfN ); + c1.resize( halfN ); + y1.resize( halfN ); + a2.resize( halfN ); + b2.resize( halfN ); + c2.resize( halfN ); + y2.resize( halfN ); + for ( int i = 0; i < halfN; ++ i ) + { + int ieven = 2 * i; + int iodd = ieven + 1; + a1[ i ] = a[ ieven ]; + b1[ i ] = b[ ieven ]; + c1[ i ] = c[ ieven ]; + y1[ i ] = y[ ieven ]; + + a2[ i ] = a[ iodd ]; + b2[ i ] = b[ iodd ]; + c2[ i ] = c[ iodd ]; + y2[ i ] = y[ iodd ]; + } +} + +void CyclicReduction( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & abar, + std::vector & bbar, + std::vector & cbar, + std::vector & ybar + ) +{ + int totalN = a.size(); + int N = totalN - 2; + for ( int i = 1; i <= N; ++ i ) + { + int in = std::max( 0, i - 1 ); + int ip = std::min( N + 1, i + 1 ); + + double alpha = - a[ i ] / b[ in ]; + double beta = - c[ i ] / b[ ip ]; + + abar[ i ] = alpha * a[ in ]; + cbar[ i ] = beta * c[ ip ]; + bbar[ i ] = b[ i ] + alpha * c[ in ] + beta * a[ ip ]; + ybar[ i ] = y[ i ] + alpha * y[ in ] + beta * y[ ip ]; + } +} + +void CR +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int totalN = a.size(); + int N = totalN - 2; + int halfN = N / 2; + int totalHalfN = halfN + 2; + a1.resize( totalHalfN ); + b1.resize( totalHalfN ); + c1.resize( totalHalfN ); + y1.resize( totalHalfN ); + + a2.resize( totalHalfN ); + b2.resize( totalHalfN ); + c2.resize( totalHalfN ); + y2.resize( totalHalfN ); + for ( int i = 1; i <= halfN; ++ i ) + { + int iodd = 2 * i - 1; + int ieven = iodd + 1; + + a1[ i ] = a[ iodd ]; + b1[ i ] = b[ iodd ]; + c1[ i ] = c[ iodd ]; + y1[ i ] = y[ iodd ]; + + a2[ i ] = a[ ieven ]; + b2[ i ] = b[ ieven ]; + c2[ i ] = c[ ieven ]; + y2[ i ] = y[ ieven ]; + } +} + +void Create( std::vector & a, std::vector & aNew ) +{ + aNew.assign( a.begin() + 1, a.end() - 1 ); +} + +void crtridiag( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & x + ) +{ + int totalN = a.size(); + int N = totalN - 2; + x.resize( N ); + if ( N == 1 ) + { + x[ 0 ] = y[ 1 ] / b[ 1 ]; + return; + } + + std::vector anew; + std::vector bnew; + std::vector cnew; + std::vector ynew; + + Create( a, anew ); + Create( b, bnew ); + Create( c, cnew ); + Create( y, ynew ); + + thomas_algorithm( anew, bnew, cnew, ynew, x ); + Print( x, "x-thomas_algorithm" ); + + Boundary( a, b, c, y ); + + std::vector acr( a.size() ); + std::vector bcr( b.size() ); + std::vector ccr( c.size() ); + std::vector ycr( y.size() ); + + CyclicReduction( a, b, c, y, acr, bcr, ccr, ycr ); + + std::vector a1, b1, c1, y1; + std::vector a2, b2, c2, y2; + + CR( acr, bcr, ccr, ycr, a1, b1, c1, y1, a2, b2, c2, y2 ); + + std::vector x1; + crtridiag( a1, b1, c1, y1, x1 ); + Print( x1, "x1" ); + std::vector a1new,b1new,c1new,y1new; + Create( a1, a1new ); + Create( b1, b1new ); + Create( c1, c1new ); + Create( y1, y1new ); + std::vector xx1( y1new.size() ); + thomas_algorithm( a1new, b1new, c1new, y1new, xx1 ); + Print( xx1, "xx1" ); + + std::vector x2; + crtridiag( a2, b2, c2, y2, x2 ); + Print( x2, "x2" ); + + std::vector a2new,b2new,c2new,y2new; + Create( a2, a2new ); + Create( b2, b2new ); + Create( c2, c2new ); + Create( y2, y2new ); + std::vector xx2( y2new.size() ); + thomas_algorithm( a2new, b2new, c2new, y2new, xx2 ); + Print( xx2, "xx2" ); + + std::vector xx; + for ( int i = 0; i < x1.size(); ++ i ) + { + xx.push_back( x1[ i ] ); + xx.push_back( x2[ i ] ); + } + Print( xx, "xx" ); + x = xx; +} + +int main( int argc, char ** argv ) +{ + const int N = 8; + + int totalN = N + 2; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 1.0 ); + std::vector x; + + crtridiag( a, b, c, y, x ); + + Print( x, "xFinal" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/01g/CMakeLists.txt b/example/numerical/tdma/cpp/01g/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01g/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01g/main.cpp b/example/numerical/tdma/cpp/01g/main.cpp new file mode 100644 index 00000000..dc2e8a43 --- /dev/null +++ b/example/numerical/tdma/cpp/01g/main.cpp @@ -0,0 +1,243 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void Boundary( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y ) +{ + int totalN = a.size(); + int N = totalN - 2; + a[ 0 ] = 0; + a[ 1 ] = 0; + b[ 0 ] = 1; + b[ N + 1 ] = 1; + c[ N ] = 0; + c[ N + 1 ] = 0; + y[ 0 ] = 0; + y[ N + 1 ] = 0; +} + +void SetCyclicReductionValue +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int N = a.size(); + int halfN = N / 2; + a1.resize( halfN ); + b1.resize( halfN ); + c1.resize( halfN ); + y1.resize( halfN ); + a2.resize( halfN ); + b2.resize( halfN ); + c2.resize( halfN ); + y2.resize( halfN ); + for ( int i = 0; i < halfN; ++ i ) + { + int ieven = 2 * i; + int iodd = ieven + 1; + a1[ i ] = a[ ieven ]; + b1[ i ] = b[ ieven ]; + c1[ i ] = c[ ieven ]; + y1[ i ] = y[ ieven ]; + + a2[ i ] = a[ iodd ]; + b2[ i ] = b[ iodd ]; + c2[ i ] = c[ iodd ]; + y2[ i ] = y[ iodd ]; + } +} + +void CyclicReduction( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & abar, + std::vector & bbar, + std::vector & cbar, + std::vector & ybar + ) +{ + int totalN = a.size(); + int N = totalN - 2; + for ( int i = 1; i <= N; ++ i ) + { + int in = std::max( 0, i - 1 ); + int ip = std::min( N + 1, i + 1 ); + + double alpha = - a[ i ] / b[ in ]; + double beta = - c[ i ] / b[ ip ]; + + abar[ i ] = alpha * a[ in ]; + cbar[ i ] = beta * c[ ip ]; + bbar[ i ] = b[ i ] + alpha * c[ in ] + beta * a[ ip ]; + ybar[ i ] = y[ i ] + alpha * y[ in ] + beta * y[ ip ]; + } +} + +void CR +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int totalN = a.size(); + int N = totalN - 2; + int halfN = N / 2; + int totalHalfN = halfN + 2; + a1.resize( totalHalfN ); + b1.resize( totalHalfN ); + c1.resize( totalHalfN ); + y1.resize( totalHalfN ); + + a2.resize( totalHalfN ); + b2.resize( totalHalfN ); + c2.resize( totalHalfN ); + y2.resize( totalHalfN ); + for ( int i = 1; i <= halfN; ++ i ) + { + int iodd = 2 * i - 1; + int ieven = iodd + 1; + + a1[ i ] = a[ iodd ]; + b1[ i ] = b[ iodd ]; + c1[ i ] = c[ iodd ]; + y1[ i ] = y[ iodd ]; + + a2[ i ] = a[ ieven ]; + b2[ i ] = b[ ieven ]; + c2[ i ] = c[ ieven ]; + y2[ i ] = y[ ieven ]; + } +} + +void Create( std::vector & a, std::vector & aNew ) +{ + aNew.assign( a.begin() + 1, a.end() - 1 ); +} + +void crtridiag( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & x + ) +{ + int totalN = a.size(); + int N = totalN - 2; + x.resize( N ); + if ( N == 1 ) + { + x[ 0 ] = y[ 1 ] / b[ 1 ]; + return; + } + + Boundary( a, b, c, y ); + + std::vector acr( a.size() ); + std::vector bcr( b.size() ); + std::vector ccr( c.size() ); + std::vector ycr( y.size() ); + + CyclicReduction( a, b, c, y, acr, bcr, ccr, ycr ); + + std::vector a1, b1, c1, y1; + std::vector a2, b2, c2, y2; + + CR( acr, bcr, ccr, ycr, a1, b1, c1, y1, a2, b2, c2, y2 ); + + std::vector x1; + crtridiag( a1, b1, c1, y1, x1 ); + + Print( x1, std::format( "x1(N={})", N ) ); + std::vector x2; + crtridiag( a2, b2, c2, y2, x2 ); + Print( x2, std::format( "x2(N={})", N ) ); + + std::vector xx; + for ( int i = 0; i < x1.size(); ++ i ) + { + xx.push_back( x1[ i ] ); + xx.push_back( x2[ i ] ); + } + Print( xx, std::format( "x1+2(N={})", N ) ); + x = xx; +} + +int main( int argc, char ** argv ) +{ + const int N = 8; + + int totalN = N + 2; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 1.0 ); + std::vector x; + + crtridiag( a, b, c, y, x ); + + Print( x, "xFinal" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/01h/CMakeLists.txt b/example/numerical/tdma/cpp/01h/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01h/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01h/main.cpp b/example/numerical/tdma/cpp/01h/main.cpp new file mode 100644 index 00000000..95ff8562 --- /dev/null +++ b/example/numerical/tdma/cpp/01h/main.cpp @@ -0,0 +1,203 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void Boundary( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y ) +{ + int totalN = a.size(); + int N = totalN - 2; + a[ 0 ] = 0; + a[ 1 ] = 0; + b[ 0 ] = 1; + b[ N + 1 ] = 1; + c[ N ] = 0; + c[ N + 1 ] = 0; + y[ 0 ] = 0; + y[ N + 1 ] = 0; +} + +void CyclicReduction( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y + ) +{ + int totalN = a.size(); + int N = totalN - 2; + std::vector abar( totalN ); + std::vector bbar( totalN ); + std::vector cbar( totalN ); + std::vector ybar( totalN ); + for ( int i = 1; i <= N; ++ i ) + { + int in = std::max( 0, i - 1 ); + int ip = std::min( N + 1, i + 1 ); + + double alpha = - a[ i ] / b[ in ]; + double beta = - c[ i ] / b[ ip ]; + + abar[ i ] = alpha * a[ in ]; + cbar[ i ] = beta * c[ ip ]; + bbar[ i ] = b[ i ] + alpha * c[ in ] + beta * a[ ip ]; + ybar[ i ] = y[ i ] + alpha * y[ in ] + beta * y[ ip ]; + } + + for ( int i = 1; i <= N; ++ i ) + { + a[ i ] = abar[ i ]; + c[ i ] = cbar[ i ]; + b[ i ] = bbar[ i ]; + y[ i ] = ybar[ i ]; + } +} + +void CR +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int totalN = a.size(); + int N = totalN - 2; + int halfN = N / 2; + int totalHalfN = halfN + 2; + a1.resize( totalHalfN ); + b1.resize( totalHalfN ); + c1.resize( totalHalfN ); + y1.resize( totalHalfN ); + + a2.resize( totalHalfN ); + b2.resize( totalHalfN ); + c2.resize( totalHalfN ); + y2.resize( totalHalfN ); + for ( int i = 1; i <= halfN; ++ i ) + { + int iodd = 2 * i - 1; + int ieven = iodd + 1; + + a1[ i ] = a[ iodd ]; + b1[ i ] = b[ iodd ]; + c1[ i ] = c[ iodd ]; + y1[ i ] = y[ iodd ]; + + a2[ i ] = a[ ieven ]; + b2[ i ] = b[ ieven ]; + c2[ i ] = c[ ieven ]; + y2[ i ] = y[ ieven ]; + } +} + +void Create( std::vector & a, std::vector & aNew ) +{ + aNew.assign( a.begin() + 1, a.end() - 1 ); +} + +void crtridiag( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & x + ) +{ + int totalN = a.size(); + int N = totalN - 2; + x.resize( N ); + if ( N == 1 ) + { + x[ 0 ] = y[ 1 ] / b[ 1 ]; + return; + } + + Boundary( a, b, c, y ); + + CyclicReduction( a, b, c, y ); + + std::vector a1, b1, c1, y1; + std::vector a2, b2, c2, y2; + CR( a, b, c, y, a1, b1, c1, y1, a2, b2, c2, y2 ); + + std::vector x1; + crtridiag( a1, b1, c1, y1, x1 ); + + Print( x1, std::format( "x1(N={})", N ) ); + std::vector x2; + crtridiag( a2, b2, c2, y2, x2 ); + Print( x2, std::format( "x2(N={})", N ) ); + + std::vector xx; + for ( int i = 0; i < x1.size(); ++ i ) + { + xx.push_back( x1[ i ] ); + xx.push_back( x2[ i ] ); + } + Print( xx, std::format( "x1+2(N={})", N ) ); + x = xx; +} + +int main( int argc, char ** argv ) +{ + const int N = 8; + + int totalN = N + 2; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 1.0 ); + std::vector x; + + crtridiag( a, b, c, y, x ); + + Print( x, "xFinal" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/01i/CMakeLists.txt b/example/numerical/tdma/cpp/01i/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/01i/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/01i/main.cpp b/example/numerical/tdma/cpp/01i/main.cpp new file mode 100644 index 00000000..e716671b --- /dev/null +++ b/example/numerical/tdma/cpp/01i/main.cpp @@ -0,0 +1,208 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void Boundary( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y ) +{ + int totalN = a.size(); + int N = totalN - 2; + a[ 0 ] = 0; + a[ 1 ] = 0; + b[ 0 ] = 1; + b[ N + 1 ] = 1; + c[ N ] = 0; + c[ N + 1 ] = 0; + y[ 0 ] = 0; + y[ N + 1 ] = 0; +} + +void CyclicReduction( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y + ) +{ + int totalN = a.size(); + int N = totalN - 2; + std::vector abar( totalN ); + std::vector bbar( totalN ); + std::vector cbar( totalN ); + std::vector ybar( totalN ); + for ( int i = 1; i <= N; ++ i ) + { + int in = std::max( 0, i - 1 ); + int ip = std::min( N + 1, i + 1 ); + + double alpha = - a[ i ] / b[ in ]; + double beta = - c[ i ] / b[ ip ]; + + abar[ i ] = alpha * a[ in ]; + cbar[ i ] = beta * c[ ip ]; + bbar[ i ] = b[ i ] + alpha * c[ in ] + beta * a[ ip ]; + ybar[ i ] = y[ i ] + alpha * y[ in ] + beta * y[ ip ]; + } + + for ( int i = 1; i <= N; ++ i ) + { + a[ i ] = abar[ i ]; + c[ i ] = cbar[ i ]; + b[ i ] = bbar[ i ]; + y[ i ] = ybar[ i ]; + } +} + +void CR +( + std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & a1, + std::vector & b1, + std::vector & c1, + std::vector & y1, + std::vector & a2, + std::vector & b2, + std::vector & c2, + std::vector & y2 +) +{ + int totalN = a.size(); + int N = totalN - 2; + int halfN = N / 2; + int totalHalfN = halfN + 2; + a1.resize( totalHalfN ); + b1.resize( totalHalfN ); + c1.resize( totalHalfN ); + y1.resize( totalHalfN ); + + a2.resize( totalHalfN ); + b2.resize( totalHalfN ); + c2.resize( totalHalfN ); + y2.resize( totalHalfN ); + for ( int i = 1; i <= halfN; ++ i ) + { + int iodd = 2 * i - 1; + int ieven = iodd + 1; + + a1[ i ] = a[ iodd ]; + b1[ i ] = b[ iodd ]; + c1[ i ] = c[ iodd ]; + y1[ i ] = y[ iodd ]; + + a2[ i ] = a[ ieven ]; + b2[ i ] = b[ ieven ]; + c2[ i ] = c[ ieven ]; + y2[ i ] = y[ ieven ]; + } +} + +void Create( std::vector & a, std::vector & aNew ) +{ + aNew.assign( a.begin() + 1, a.end() - 1 ); +} + +void crtridiag( std::vector & a, + std::vector & b, + std::vector & c, + std::vector & y, + std::vector & x + ) +{ + int totalN = a.size(); + int N = totalN - 2; + x.resize( N ); + if ( N == 1 ) + { + x[ 0 ] = y[ 1 ] / b[ 1 ]; + return; + } + + Boundary( a, b, c, y ); + + CyclicReduction( a, b, c, y ); + + std::vector a1, b1, c1, y1; + std::vector a2, b2, c2, y2; + CR( a, b, c, y, a1, b1, c1, y1, a2, b2, c2, y2 ); + + std::vector x1; + crtridiag( a1, b1, c1, y1, x1 ); + + Print( x1, std::format( "x1(N={})", N ) ); + std::vector x2; + crtridiag( a2, b2, c2, y2, x2 ); + Print( x2, std::format( "x2(N={})", N ) ); + + std::vector xx; + + int halfN = N / 2; + for ( int i = 0; i < halfN; ++ i ) + { + int i1 = 2 * i; + int i2 = i1 + 1; + x[ i1 ] = x1[ i ]; + x[ i2 ] = x2[ i ]; + std::print( "i1={}\n", i1 ); + std::print( "i2={}\n", i2 ); + } + Print( x, std::format( "x1+2(N={})", N ) ); +} + +int main( int argc, char ** argv ) +{ + const int N = 8; + + int totalN = N + 2; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 1.0 ); + std::vector x; + + crtridiag( a, b, c, y, x ); + + Print( x, "xFinal" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/02/CMakeLists.txt b/example/numerical/tdma/cpp/02/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/02/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/02/main.cpp b/example/numerical/tdma/cpp/02/main.cpp new file mode 100644 index 00000000..33f4ef1e --- /dev/null +++ b/example/numerical/tdma/cpp/02/main.cpp @@ -0,0 +1,70 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + int p = 3; + int N = std::pow( 2, p ) - 1; + int totalN = N; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 0.0 ); + a[ 0 ] = 0; + c[ N - 1 ] = 0; + + y[ 0 ] = 1; + y[ N - 1 ] = 1; + + //for ( int i = 0; i < N; ++ i ) + //{ + // y[ i ] = i; + //} + + std::vector x( y.size() ); + + thomas_algorithm( a, b, c, y, x ); + Print( x, "x" ); + + int kkk = 1; + + return 0; +} diff --git a/example/numerical/tdma/cpp/02a/CMakeLists.txt b/example/numerical/tdma/cpp/02a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/02a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/02a/main.cpp b/example/numerical/tdma/cpp/02a/main.cpp new file mode 100644 index 00000000..c78b9d90 --- /dev/null +++ b/example/numerical/tdma/cpp/02a/main.cpp @@ -0,0 +1,79 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + int p = 3; + int N0 = std::pow( 2, p ) - 1; + int N = N0 + 5; + int totalN = std::pow( 2, p + 1 ) - 1; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 0.0 ); + a[ 0 ] = 0; + c[ N - 1 ] = 0; + + y[ 0 ] = 1; + y[ N - 1 ] = 1; + + for ( int i = N; i < totalN; ++ i ) + { + a[ i ] = 0; + c[ i ] = 0; + b[ i ] = 1; + y[ i ] = 0; + } + + //for ( int i = 0; i < N; ++ i ) + //{ + // y[ i ] = i; + //} + + std::vector x( y.size() ); + + thomas_algorithm( a, b, c, y, x ); + Print( x, "x" ); + + int kkk = 1; + + return 0; +} diff --git a/example/numerical/tdma/cpp/02b/CMakeLists.txt b/example/numerical/tdma/cpp/02b/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/02b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/02b/main.cpp b/example/numerical/tdma/cpp/02b/main.cpp new file mode 100644 index 00000000..e4a953b2 --- /dev/null +++ b/example/numerical/tdma/cpp/02b/main.cpp @@ -0,0 +1,80 @@ +import std; + +void Print( std::vector & x, const std::string &name="vector") +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + int p = 3; + int N0 = std::pow( 2, p ) - 1; + int N = N0 + 5; + int totalN = std::pow( 2, p + 1 ) - 1; + std::vector a( totalN, -1 ); + std::vector b( totalN, 2 ); + std::vector c( totalN, -1 ); + std::vector y( totalN, 0.0 ); + a[ 0 ] = 0; + c[ N - 1 ] = 0; + + //y[ 0 ] = 1; + //y[ N - 1 ] = 1; + + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = i; + } + + for ( int i = N; i < totalN; ++ i ) + { + a[ i ] = 0; + c[ i ] = 0; + b[ i ] = 1; + y[ i ] = 0; + } + + + std::vector x( y.size() ); + + thomas_algorithm( a, b, c, y, x ); + Print( x, "x" ); + + int kkk = 1; + + return 0; +} diff --git a/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01/CMakeLists.txt b/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01/main.cpp b/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01/main.cpp new file mode 100644 index 00000000..1ffccba6 --- /dev/null +++ b/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01/main.cpp @@ -0,0 +1,152 @@ +import std; + +template +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::print( "{:4.1f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + +void FillA( const std::vector &a, + const std::vector &b, + const std::vector &c, + std::vector> &A ) +{ + int N = a.size(); + A.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + if ( i >= 1 ) + { + A[ i ][ i - 1 ] = a[ i ]; + } + A[ i ][ i ] = b[ i ]; + if ( i < N - 1 ) + { + A[ i ][ i + 1 ] = c[ i ]; + } + } +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void cyclic_thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = a.size(); + std::vector bNew = b; + double gamma = - b[ 0 ]; + double aa = a[ 0 ] / gamma; + bNew[ 0 ] -= gamma; + bNew[ N - 1 ] -= c[ N - 1 ] * aa; + std::vector u( N, 0 ); + std::vector v( N, 0 ); + u[ 0 ] = gamma; + u[ N - 1 ] = c[ N - 1 ]; + + v[ 0 ] = 1; + v[ N - 1 ] = a[ 0 ] / gamma; + + std::vector y( N, 0 ); + std::vector q( N, 0 ); + + thomas_algorithm( a, bNew, c, d, y ); + thomas_algorithm( a, bNew, c, u, q ); + double t1 = y[ 0 ] + aa * y[ N - 1 ]; + double t2 = q[ 0 ] + aa * q[ N - 1 ] + 1; + double tt = t1 / t2; + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = y[ i ] - tt * q[ i ]; + } +} + +int main( int argc, char ** argv ) +{ + std::vector>A{ {2,1,0,7},{-1,7,4,0},{0,2,-3,2},{6,0,1,8} }; + Print( A, "A" ); + + std::vector q{ 32, 25, -5, 41 }; + + std::vector a{ 7, -1, 2, 1 }; + std::vector b{ 2, 7, -3, 8 }; + std::vector c{ 1, 4, 2, 6 }; + std::vector d{ 32, 25, -5, 41 }; + + std::vector x( q.size() ); + + cyclic_thomas_algorithm( a, b, c, d, x ); + Print( x, "x" ); + + std::vector y( d.size() ); + + MatrixMultiply( A, x, y ); + Print( y, "y" ); + Print( d, "d" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01a/CMakeLists.txt b/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01a/main.cpp b/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01a/main.cpp new file mode 100644 index 00000000..47792d13 --- /dev/null +++ b/example/numerical/tdma/cpp/periodic-tridiagonal/serial/01a/main.cpp @@ -0,0 +1,215 @@ +import std; + +template +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::print( "{:4.1f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + +void FillMatrix( const std::vector &a, + const std::vector &b, + const std::vector &c, + std::vector> &A ) +{ + int N = a.size(); + A.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + if ( i >= 1 ) + { + A[ i ][ i - 1 ] = a[ i ]; + } + A[ i ][ i ] = b[ i ]; + if ( i < N - 1 ) + { + A[ i ][ i + 1 ] = c[ i ]; + } + } +} + +void FillCyclicMatrix( const std::vector &a, + const std::vector &b, + const std::vector &c, + std::vector> &A ) +{ + int N = a.size(); + A.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + if ( i >= 1 ) + { + A[ i ][ i - 1 ] = a[ i ]; + } + A[ i ][ i ] = b[ i ]; + if ( i < N - 1 ) + { + A[ i ][ i + 1 ] = c[ i ]; + } + } + A[ 0 ][ N - 1 ] = a[ 0 ]; + A[ N - 1 ][ 0 ] = c[ N - 1 ]; +} + +void thomas_algorithm( + int N, + const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double coef = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + c_star[ i ] = c[ i ] * coef; + d_star[ i ] = ( d[ i ] - a[ i ] * d_star[ i - 1 ] ) * coef; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +void thomas_algorithm( + const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + thomas_algorithm( N, a, b, c, d, x ); +} + +void cyclic_thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = a.size(); + std::vector bNew = b; + double gamma = - b[ 0 ]; + double aa = a[ 0 ] / gamma; + bNew[ 0 ] -= gamma; + bNew[ N - 1 ] -= c[ N - 1 ] * aa; + std::vector u( N, 0 ); + std::vector v( N, 0 ); + u[ 0 ] = gamma; + u[ N - 1 ] = c[ N - 1 ]; + + v[ 0 ] = 1; + v[ N - 1 ] = a[ 0 ] / gamma; + + std::vector y( N, 0 ); + std::vector q( N, 0 ); + + thomas_algorithm( a, bNew, c, d, y ); + thomas_algorithm( a, bNew, c, u, q ); + double t1 = y[ 0 ] + aa * y[ N - 1 ]; + double t2 = q[ 0 ] + aa * q[ N - 1 ] + 1; + double tt = t1 / t2; + + for ( int i = 0; i < N; ++ i ) + { + x[ i ] = y[ i ] - tt * q[ i ]; + } +} + +void cyclic_thomas_algorithm_version1( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = a.size(); + std::vector u( N, 0 ); + u[ 0 ] = -a[ 0 ]; + u[ N - 2 ] = -c[ N - 2 ]; + + std::vector xx1( N, 0 ); + std::vector xx2( N, 0 ); + + thomas_algorithm( N - 1, a, b, c, d, xx1 ); + thomas_algorithm( N - 1, a, b, c, u, xx2 ); + + double tt1 = d[ N - 1 ] - c[ N - 1 ] * xx1[ 0 ] - a[ N - 1 ] * xx1[ N - 2 ]; + double tt2 = b[ N - 1 ] + c[ N - 1 ] * xx2[ 0 ] + a[ N - 1 ] * xx2[ N - 2 ]; + double xn = tt1 / tt2; + + for ( int i = 0; i < N - 1; ++ i ) + { + x[ i ] = xx1[ i ] + xx2[ i ] * xn; + } + x[ N - 1 ] = xn; +} + +int main( int argc, char ** argv ) +{ + std::vector a{ 7, -1, 2, 1 }; + std::vector b{ 2, 7, -3, 8 }; + std::vector c{ 1, 4, 2, 6 }; + std::vector d{ 32, 25, -5, 41 }; + + std::vector> A; + FillCyclicMatrix( a, b, c, A ); + Print( A, "A" ); + + std::vector x( d.size() ); + + //cyclic_thomas_algorithm( a, b, c, d, x ); + cyclic_thomas_algorithm_version1( a, b, c, d, x ); + Print( x, "x" ); + + std::vector y( d.size() ); + + MatrixMultiply( A, x, y ); + Print( y, "y" ); + Print( d, "d" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01/CMakeLists.txt new file mode 100644 index 00000000..b17c6cea --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01/main.cpp new file mode 100644 index 00000000..3021f9e9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01/main.cpp @@ -0,0 +1,83 @@ +#include "mpi.h" +import std; + +int main( int argc, char ** argv ) +{ + //MPI initialization and both memory allocation and generation of the matrix A + int i, j, k, size, index; + int index1, index2; + int mynode, totalnodes; + double alpha, gamma; + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &totalnodes ); + MPI_Comm_rank( MPI_COMM_WORLD, &mynode ); + size = (int)std::pow( 2, std::log2( totalnodes + 1 ) + 1 ) - 1; + std::print( "size={}", size ); + double ** A = new double * [ numrows ]; + for ( i = 0; i < numrows; i++ ) + { + A[ i ] = new double[ size + 1 ]; + for ( j = 0; j < size + 1; j++ ) + { + A[ i ][ j ] = 0.0; + } + } + if ( mynode == 0 ) + { + A[ 0 ][ 0 ] = -2.0; A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; A[ 1 ][ 1 ] = -2.0; A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; A[ 2 ][ 2 ] = -2.0; A[ 2 ][ 3 ] = 1.0; + } + else if ( mynode == ( totalnodes - 1 ) ) + { + index = 2 * mynode; + A[ 0 ][ index - 1 ] = 1.0; A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + index = 2 * mynode + 1; + A[ 1 ][ index - 1 ] = 1.0; A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ size - 2 ] = 1.0; A[ 2 ][ size - 1 ] = -2.0; + } + else + { + for ( i = 0; i < 3; i++ ) + { + index = i + 2 * mynode; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( i = 0; i < 3; i++ ) + { + A[ i ][ size ] = 2 * mynode + i; + } + int numactivep = totalnodes; + int * activep = new int[ totalnodes ]; + for ( j = 0; j < numactivep; j++ ) + { + activep[ j ] = j; + } + + for ( j = 0; j < size + 1; j++ ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + + /* Part 3 */ + double * x = new double[ totalnodes ]; + + delete[] activep; + for ( i = 0; i < numrows; i++ ) + { + delete[] A[ i ]; + } + delete[] A; + delete[] x; + MPI_Finalize(); + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01a/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01a/CMakeLists.txt new file mode 100644 index 00000000..b17c6cea --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01a/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01a/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01a/main.cpp new file mode 100644 index 00000000..71db9f5c --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01a/main.cpp @@ -0,0 +1,137 @@ +#include "mpi.h" +import std; + +int main( int argc, char ** argv ) +{ + //MPI initialization and both memory allocation and generation of the matrix A + int i, j, k, size, index; + int index1, index2; + int mynode, totalnodes; + double alpha, gamma; + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &totalnodes ); + MPI_Comm_rank( MPI_COMM_WORLD, &mynode ); + size = (int)std::pow( 2, std::log2( totalnodes + 1 ) + 1 ) - 1; + std::print( "size={}", size ); + double ** A = new double * [ numrows ]; + for ( i = 0; i < numrows; i++ ) + { + A[ i ] = new double[ size + 1 ]; + for ( j = 0; j < size + 1; j++ ) + { + A[ i ][ j ] = 0.0; + } + } + if ( mynode == 0 ) + { + A[ 0 ][ 0 ] = -2.0; A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; A[ 1 ][ 1 ] = -2.0; A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; A[ 2 ][ 2 ] = -2.0; A[ 2 ][ 3 ] = 1.0; + } + else if ( mynode == ( totalnodes - 1 ) ) + { + index = 2 * mynode; + A[ 0 ][ index - 1 ] = 1.0; A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + index = 2 * mynode + 1; + A[ 1 ][ index - 1 ] = 1.0; A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ size - 2 ] = 1.0; A[ 2 ][ size - 1 ] = -2.0; + } + else + { + for ( i = 0; i < 3; i++ ) + { + index = i + 2 * mynode; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( i = 0; i < 3; i++ ) + { + A[ i ][ size ] = 2 * mynode + i; + } + int numactivep = totalnodes; + int * activep = new int[ totalnodes ]; + for ( j = 0; j < numactivep; j++ ) + { + activep[ j ] = j; + } + + for ( j = 0; j < size + 1; j++ ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + + /* Part 2 */ + //Cyclic reduction + + for ( i = 0; i < log2( size + 1 ) - 1; i++ ) + { + for ( j = 0; j < numactivep; j++ ) + { + if ( mynode == activep[ j ] ) + { + index1 = 2 * mynode + 1 - pow( 2, i ); + index2 = 2 * mynode + 1 + pow( 2, i ); + alpha = A[ 1 ][ index1 ] / A[ 3 ][ index1 ]; + gamma = A[ 1 ][ index2 ] / A[ 4 ][ index2 ]; + for ( k = 0; k < size + 1; k++ ) + { + A[ 1 ][ k ] -= ( alpha * A[ 3 ][ k ] + gamma * A[ 4 ][ k ] ); + } + if ( numactivep > 1 ) + { + if ( j == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ 1 ], 0, + MPI_COMM_WORLD ); + } + else if ( j == numactivep - 1 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ numactivep - 2 ], + 1, MPI_COMM_WORLD ); + } + else if ( j % 2 == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], + 1, MPI_COMM_WORLD ); + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], + 0, MPI_COMM_WORLD ); + } + else + { + MPI_Recv( A[ 3 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], 0, + MPI_COMM_WORLD, &status ); + MPI_Recv( A[ 4 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], 1, + MPI_COMM_WORLD, &status ); + } + } + } + } + numactivep = 0; + for ( j = activep[ 1 ]; j < totalnodes; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep++ ] = j; + } + } + + /* Part 3 */ + //Part 3 - Back substitution + double * x = new double[ totalnodes ]; + + delete[] activep; + for ( i = 0; i < numrows; i++ ) + { + delete[] A[ i ]; + } + delete[] A; + delete[] x; + MPI_Finalize(); + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01b/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01b/CMakeLists.txt new file mode 100644 index 00000000..b17c6cea --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01b/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01b/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01b/main.cpp new file mode 100644 index 00000000..920aad4e --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01b/main.cpp @@ -0,0 +1,180 @@ +#include "mpi.h" +import std; + +int main( int argc, char ** argv ) +{ + //MPI initialization and both memory allocation and generation of the matrix A + int i, j, k, size, index; + int index1, index2; + int mynode, totalnodes; + double alpha, gamma; + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &totalnodes ); + MPI_Comm_rank( MPI_COMM_WORLD, &mynode ); + size = (int)std::pow( 2, std::log2( totalnodes + 1 ) + 1 ) - 1; + std::print( "size={}", size ); + double ** A = new double * [ numrows ]; + for ( i = 0; i < numrows; i++ ) + { + A[ i ] = new double[ size + 1 ]; + for ( j = 0; j < size + 1; j++ ) + { + A[ i ][ j ] = 0.0; + } + } + if ( mynode == 0 ) + { + A[ 0 ][ 0 ] = -2.0; A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; A[ 1 ][ 1 ] = -2.0; A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; A[ 2 ][ 2 ] = -2.0; A[ 2 ][ 3 ] = 1.0; + } + else if ( mynode == ( totalnodes - 1 ) ) + { + index = 2 * mynode; + A[ 0 ][ index - 1 ] = 1.0; A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + index = 2 * mynode + 1; + A[ 1 ][ index - 1 ] = 1.0; A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ size - 2 ] = 1.0; A[ 2 ][ size - 1 ] = -2.0; + } + else + { + for ( i = 0; i < 3; i++ ) + { + index = i + 2 * mynode; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( i = 0; i < 3; i++ ) + { + A[ i ][ size ] = 2 * mynode + i; + } + int numactivep = totalnodes; + int * activep = new int[ totalnodes ]; + for ( j = 0; j < numactivep; j++ ) + { + activep[ j ] = j; + } + + for ( j = 0; j < size + 1; j++ ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + + /* Part 2 */ + //Cyclic reduction + + for ( i = 0; i < log2( size + 1 ) - 1; i++ ) + { + for ( j = 0; j < numactivep; j++ ) + { + if ( mynode == activep[ j ] ) + { + index1 = 2 * mynode + 1 - pow( 2, i ); + index2 = 2 * mynode + 1 + pow( 2, i ); + alpha = A[ 1 ][ index1 ] / A[ 3 ][ index1 ]; + gamma = A[ 1 ][ index2 ] / A[ 4 ][ index2 ]; + for ( k = 0; k < size + 1; k++ ) + { + A[ 1 ][ k ] -= ( alpha * A[ 3 ][ k ] + gamma * A[ 4 ][ k ] ); + } + if ( numactivep > 1 ) + { + if ( j == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ 1 ], 0, + MPI_COMM_WORLD ); + } + else if ( j == numactivep - 1 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ numactivep - 2 ], + 1, MPI_COMM_WORLD ); + } + else if ( j % 2 == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], + 1, MPI_COMM_WORLD ); + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], + 0, MPI_COMM_WORLD ); + } + else + { + MPI_Recv( A[ 3 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], 0, + MPI_COMM_WORLD, &status ); + MPI_Recv( A[ 4 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], 1, + MPI_COMM_WORLD, &status ); + } + } + } + } + numactivep = 0; + for ( j = activep[ 1 ]; j < totalnodes; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep++ ] = j; + } + } + + /* Part 3 */ + //Part 3 - Back substitution + double * x = new double[ totalnodes ]; + for ( j = 0; j < totalnodes; j++ ) + { + x[ j ] = 0.0; + } + if ( mynode == activep[ 0 ] ) + { + x[ mynode ] = A[ 1 ][ size ] / A[ 1 ][ ( size - 1 ) / 2 ]; + } + double tmp; + for ( i = log2( size + 1 ) - 3; i >= 0; i-- ) + { + tmp = x[ mynode ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, + MPI_COMM_WORLD ); + numactivep = 0; + for ( j = activep[ 0 ] - pow( 2, i ); j < totalnodes; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep++ ] = j; + } + for ( j = 0; j < numactivep; j++ ) + { + if ( mynode == activep[ j ] ) + { + x[ mynode ] = A[ 1 ][ size ]; + for ( k = 0; k < totalnodes; k++ ) + { + if ( k != mynode ) + { + x[ mynode ] -= A[ 1 ][ 2 * k + 1 ] * x[ k ]; + } + } + x[ mynode ] = x[ mynode ] / A[ 1 ][ 2 * mynode + 1 ]; + } + } + } + + tmp = x[ mynode ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, + MPI_COMM_WORLD ); + + /* Part 4 */ + //Part 4 - Solving for odd rows + + + delete[] activep; + for ( i = 0; i < numrows; i++ ) + { + delete[] A[ i ]; + } + delete[] A; + delete[] x; + MPI_Finalize(); + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01c/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01c/CMakeLists.txt new file mode 100644 index 00000000..b17c6cea --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01c/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01c/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01c/main.cpp new file mode 100644 index 00000000..6128ece2 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01c/main.cpp @@ -0,0 +1,213 @@ +#include "mpi.h" +import std; + +int main( int argc, char ** argv ) +{ + //MPI initialization and both memory allocation and generation of the matrix A + int i, j, k, size, index; + int index1, index2; + int mynode, totalnodes; + double alpha, gamma; + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &totalnodes ); + MPI_Comm_rank( MPI_COMM_WORLD, &mynode ); + size = (int)std::pow( 2, std::log2( totalnodes + 1 ) + 1 ) - 1; + std::print( "size={}", size ); + double ** A = new double * [ numrows ]; + for ( i = 0; i < numrows; i++ ) + { + A[ i ] = new double[ size + 1 ]; + for ( j = 0; j < size + 1; j++ ) + { + A[ i ][ j ] = 0.0; + } + } + if ( mynode == 0 ) + { + A[ 0 ][ 0 ] = -2.0; A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; A[ 1 ][ 1 ] = -2.0; A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; A[ 2 ][ 2 ] = -2.0; A[ 2 ][ 3 ] = 1.0; + } + else if ( mynode == ( totalnodes - 1 ) ) + { + index = 2 * mynode; + A[ 0 ][ index - 1 ] = 1.0; A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + index = 2 * mynode + 1; + A[ 1 ][ index - 1 ] = 1.0; A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ size - 2 ] = 1.0; A[ 2 ][ size - 1 ] = -2.0; + } + else + { + for ( i = 0; i < 3; i++ ) + { + index = i + 2 * mynode; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( i = 0; i < 3; i++ ) + { + A[ i ][ size ] = 2 * mynode + i; + } + int numactivep = totalnodes; + int * activep = new int[ totalnodes ]; + for ( j = 0; j < numactivep; j++ ) + { + activep[ j ] = j; + } + + for ( j = 0; j < size + 1; j++ ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + + /* Part 2 */ + //Cyclic reduction + + for ( i = 0; i < log2( size + 1 ) - 1; i++ ) + { + for ( j = 0; j < numactivep; j++ ) + { + if ( mynode == activep[ j ] ) + { + index1 = 2 * mynode + 1 - pow( 2, i ); + index2 = 2 * mynode + 1 + pow( 2, i ); + alpha = A[ 1 ][ index1 ] / A[ 3 ][ index1 ]; + gamma = A[ 1 ][ index2 ] / A[ 4 ][ index2 ]; + for ( k = 0; k < size + 1; k++ ) + { + A[ 1 ][ k ] -= ( alpha * A[ 3 ][ k ] + gamma * A[ 4 ][ k ] ); + } + if ( numactivep > 1 ) + { + if ( j == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ 1 ], 0, + MPI_COMM_WORLD ); + } + else if ( j == numactivep - 1 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ numactivep - 2 ], + 1, MPI_COMM_WORLD ); + } + else if ( j % 2 == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], + 1, MPI_COMM_WORLD ); + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], + 0, MPI_COMM_WORLD ); + } + else + { + MPI_Recv( A[ 3 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], 0, + MPI_COMM_WORLD, &status ); + MPI_Recv( A[ 4 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], 1, + MPI_COMM_WORLD, &status ); + } + } + } + } + numactivep = 0; + for ( j = activep[ 1 ]; j < totalnodes; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep++ ] = j; + } + } + + /* Part 3 */ + //Part 3 - Back substitution + double * x = new double[ totalnodes ]; + for ( j = 0; j < totalnodes; j++ ) + { + x[ j ] = 0.0; + } + if ( mynode == activep[ 0 ] ) + { + x[ mynode ] = A[ 1 ][ size ] / A[ 1 ][ ( size - 1 ) / 2 ]; + } + double tmp; + for ( i = log2( size + 1 ) - 3; i >= 0; i-- ) + { + tmp = x[ mynode ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, + MPI_COMM_WORLD ); + numactivep = 0; + for ( j = activep[ 0 ] - pow( 2, i ); j < totalnodes; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep++ ] = j; + } + for ( j = 0; j < numactivep; j++ ) + { + if ( mynode == activep[ j ] ) + { + x[ mynode ] = A[ 1 ][ size ]; + for ( k = 0; k < totalnodes; k++ ) + { + if ( k != mynode ) + { + x[ mynode ] -= A[ 1 ][ 2 * k + 1 ] * x[ k ]; + } + } + x[ mynode ] = x[ mynode ] / A[ 1 ][ 2 * mynode + 1 ]; + } + } + } + + tmp = x[ mynode ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, + MPI_COMM_WORLD ); + + /* Part 4 */ + //Part 4 - Solving for odd rows + + for ( k = 0; k < totalnodes; k++ ) + { + A[ 0 ][ size ] -= A[ 0 ][ 2 * k + 1 ] * x[ k ]; + A[ 2 ][ size ] -= A[ 2 ][ 2 * k + 1 ] * x[ k ]; + } + A[ 0 ][ size ] = A[ 0 ][ size ] / A[ 0 ][ 2 * mynode ]; + A[ 1 ][ size ] = x[ mynode ]; + + A[ 2 ][ size ] = A[ 2 ][ size ] / A[ 2 ][ 2 * mynode + 2 ]; + + std::print( "totalnodes={}\n", totalnodes ); + + if ( mynode == 0 ) + { + std::print( "mynode = {}, x = ", mynode ); + for ( j = 0; j < totalnodes; j++ ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + } + else if ( mynode == ( totalnodes - 1 ) ) + { + std::print( "mynode = {}, x = ", mynode ); + for ( j = 0; j < totalnodes; j++ ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + + } + + + delete[] activep; + for ( i = 0; i < numrows; i++ ) + { + delete[] A[ i ]; + } + delete[] A; + delete[] x; + MPI_Finalize(); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01d/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01d/CMakeLists.txt new file mode 100644 index 00000000..b17c6cea --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01d/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01d/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01d/main.cpp new file mode 100644 index 00000000..befc225b --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01d/main.cpp @@ -0,0 +1,229 @@ +#include "mpi.h" +import std; + +void Print( double ** A, int numrows, int size, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < size; ++ j ) + { + std::print( "{} ", A[ i ][ j ] ); + } + std::println(); + } +} + +int main( int argc, char ** argv ) +{ + //MPI initialization and both memory allocation and generation of the matrix A + int i, j, k, size, index; + int index1, index2; + int mynode, totalnodes; + double alpha, gamma; + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &totalnodes ); + MPI_Comm_rank( MPI_COMM_WORLD, &mynode ); + size = (int)std::pow( 2, std::log2( totalnodes + 1 ) + 1 ) - 1; + std::print( "size={}", size ); + double ** A = new double * [ numrows ]; + for ( i = 0; i < numrows; ++ i ) + { + A[ i ] = new double[ size + 1 ]; + for ( j = 0; j < size + 1; ++ j ) + { + A[ i ][ j ] = 0.0; + } + } + std::print( "mynode={}, totalnodes={}, numrows={}, size={}\n", mynode, totalnodes, numrows, size ); + Print( A, numrows, size, "Matrix A 0" ); + if ( mynode == 0 ) + { + A[ 0 ][ 0 ] = -2.0; A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; A[ 1 ][ 1 ] = -2.0; A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; A[ 2 ][ 2 ] = -2.0; A[ 2 ][ 3 ] = 1.0; + } + else if ( mynode == ( totalnodes - 1 ) ) + { + index = 2 * mynode; + A[ 0 ][ index - 1 ] = 1.0; A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + index = 2 * mynode + 1; + A[ 1 ][ index - 1 ] = 1.0; A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ size - 2 ] = 1.0; A[ 2 ][ size - 1 ] = -2.0; + } + else + { + for ( i = 0; i < 3; i++ ) + { + index = i + 2 * mynode; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( i = 0; i < 3; i++ ) + { + A[ i ][ size ] = 2 * mynode + i; + } + int numactivep = totalnodes; + int * activep = new int[ totalnodes ]; + for ( j = 0; j < numactivep; ++ j ) + { + activep[ j ] = j; + } + + for ( j = 0; j < size + 1; j++ ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + Print( A, numrows, size, "Matrix A 1" ); + + /* Part 2 */ + //Cyclic reduction + + for ( i = 0; i < log2( size + 1 ) - 1; i++ ) + { + for ( j = 0; j < numactivep; j++ ) + { + if ( mynode == activep[ j ] ) + { + index1 = 2 * mynode + 1 - pow( 2, i ); + index2 = 2 * mynode + 1 + pow( 2, i ); + alpha = A[ 1 ][ index1 ] / A[ 3 ][ index1 ]; + gamma = A[ 1 ][ index2 ] / A[ 4 ][ index2 ]; + for ( k = 0; k < size + 1; k++ ) + { + A[ 1 ][ k ] -= ( alpha * A[ 3 ][ k ] + gamma * A[ 4 ][ k ] ); + } + if ( numactivep > 1 ) + { + if ( j == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ 1 ], 0, + MPI_COMM_WORLD ); + } + else if ( j == numactivep - 1 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ numactivep - 2 ], + 1, MPI_COMM_WORLD ); + } + else if ( j % 2 == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], + 1, MPI_COMM_WORLD ); + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], + 0, MPI_COMM_WORLD ); + } + else + { + MPI_Recv( A[ 3 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], 0, + MPI_COMM_WORLD, &status ); + MPI_Recv( A[ 4 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], 1, + MPI_COMM_WORLD, &status ); + } + } + } + } + numactivep = 0; + for ( j = activep[ 1 ]; j < totalnodes; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep ++ ] = j; + } + } + + /* Part 3 */ + //Part 3 - Back substitution + double * x = new double[ totalnodes ]; + for ( j = 0; j < totalnodes; j++ ) + { + x[ j ] = 0.0; + } + if ( mynode == activep[ 0 ] ) + { + x[ mynode ] = A[ 1 ][ size ] / A[ 1 ][ ( size - 1 ) / 2 ]; + } + double tmp; + for ( i = log2( size + 1 ) - 3; i >= 0; i-- ) + { + tmp = x[ mynode ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, + MPI_COMM_WORLD ); + numactivep = 0; + for ( j = activep[ 0 ] - pow( 2, i ); j < totalnodes; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep++ ] = j; + } + for ( j = 0; j < numactivep; j++ ) + { + if ( mynode == activep[ j ] ) + { + x[ mynode ] = A[ 1 ][ size ]; + for ( k = 0; k < totalnodes; k++ ) + { + if ( k != mynode ) + { + x[ mynode ] -= A[ 1 ][ 2 * k + 1 ] * x[ k ]; + } + } + x[ mynode ] = x[ mynode ] / A[ 1 ][ 2 * mynode + 1 ]; + } + } + } + + tmp = x[ mynode ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, MPI_COMM_WORLD ); + + /* Part 4 */ + //Part 4 - Solving for odd rows + + for ( k = 0; k < totalnodes; ++ k ) + { + A[ 0 ][ size ] -= A[ 0 ][ 2 * k + 1 ] * x[ k ]; + A[ 2 ][ size ] -= A[ 2 ][ 2 * k + 1 ] * x[ k ]; + } + A[ 0 ][ size ] = A[ 0 ][ size ] / A[ 0 ][ 2 * mynode ]; + A[ 1 ][ size ] = x[ mynode ]; + A[ 2 ][ size ] = A[ 2 ][ size ] / A[ 2 ][ 2 * mynode + 2 ]; + + std::print( "totalnodes={}\n", totalnodes ); + + if ( mynode == 0 ) + { + std::print( "mynode = {}, x = ", mynode ); + for ( j = 0; j < totalnodes; j++ ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + } + else if ( mynode == ( totalnodes - 1 ) ) + { + std::print( "mynode = {}, x = ", mynode ); + for ( j = 0; j < totalnodes; j++ ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + + } + + Print( A, numrows, size, "Matrix A Final" ); + + + delete[] activep; + for ( i = 0; i < numrows; i++ ) + { + delete[] A[ i ]; + } + delete[] A; + delete[] x; + MPI_Finalize(); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01e/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01e/CMakeLists.txt new file mode 100644 index 00000000..ade49a3f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01e/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp + LogFile.h LogFile.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01e/LogFile.cpp b/example/numerical/tdma/cpp/reference/parallel/01e/LogFile.cpp new file mode 100644 index 00000000..a6cfb124 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01e/LogFile.cpp @@ -0,0 +1,138 @@ +#include "LogFile.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; +int Parallel::pid = 0; + +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/numerical/tdma/cpp/reference/parallel/01e/LogFile.h b/example/numerical/tdma/cpp/reference/parallel/01e/LogFile.h new file mode 100644 index 00000000..2f3061c4 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01e/LogFile.h @@ -0,0 +1,33 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class Parallel +{ +public: + static int pid; +}; + +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/numerical/tdma/cpp/reference/parallel/01e/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01e/main.cpp new file mode 100644 index 00000000..0c9868ee --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01e/main.cpp @@ -0,0 +1,248 @@ +#include "mpi.h" +#include "LogFile.h" +import std; + +void PrintToScreen( double ** A, int numrows, int size, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < size; ++ j ) + { + std::print( "{} ", A[ i ][ j ] ); + } + std::println(); + } +} + +void Print( double ** A, int numrows, int size, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + logFile << name << " = \n"; + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < size; ++ j ) + { + logFile << A[ i ][ j ] << " "; + } + logFile << "\n"; + } +} + +int main( int argc, char ** argv ) +{ + //MPI initialization and both memory allocation and generation of the matrix A + int size, index; + int index1, index2; + int mynode, totalnodes; + double alpha, gamma; + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &totalnodes ); + MPI_Comm_rank( MPI_COMM_WORLD, &mynode ); + + Parallel::pid = mynode; + size = (int)std::pow( 2, std::log2( totalnodes + 1 ) + 1 ) - 1; + std::print( "size={}", size ); + double ** A = new double * [ numrows ]; + for ( int i = 0; i < numrows; ++ i ) + { + A[ i ] = new double[ size + 1 ]; + for ( int j = 0; j < size + 1; ++ j ) + { + A[ i ][ j ] = 0.0; + } + } + std::print( "mynode={}, totalnodes={}, numrows={}, size={}\n", mynode, totalnodes, numrows, size ); + Print( A, numrows, size + 1, "Matrix A 0" ); + if ( mynode == 0 ) + { + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; + A[ 1 ][ 1 ] = -2.0; + A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; + A[ 2 ][ 2 ] = -2.0; + A[ 2 ][ 3 ] = 1.0; + } + else if ( mynode == ( totalnodes - 1 ) ) + { + index = 2 * mynode; + A[ 0 ][ index - 1 ] = 1.0; + A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + + index = 2 * mynode + 1; + A[ 1 ][ index - 1 ] = 1.0; + A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ size - 2 ] = 1.0; + A[ 2 ][ size - 1 ] = -2.0; + } + else + { + for ( int i = 0; i < 3; ++ i ) + { + index = i + 2 * mynode; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( int i = 0; i < 3; ++ i ) + { + A[ i ][ size ] = 2 * mynode + i; + } + int numactivep = totalnodes; + int * activep = new int[ totalnodes ]; + for ( int j = 0; j < numactivep; ++ j ) + { + activep[ j ] = j; + } + + for ( int j = 0; j < size + 1; ++ j ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + Print( A, numrows, size + 1, "Matrix A 1" ); + + /* Part 2 */ + //Cyclic reduction + + for ( int i = 0; i < log2( size + 1 ) - 1; ++ i ) + { + for ( int j = 0; j < numactivep; ++ j ) + { + if ( mynode == activep[ j ] ) + { + index1 = 2 * mynode + 1 - pow( 2, i ); + index2 = 2 * mynode + 1 + pow( 2, i ); + alpha = A[ 1 ][ index1 ] / A[ 3 ][ index1 ]; + gamma = A[ 1 ][ index2 ] / A[ 4 ][ index2 ]; + for ( int k = 0; k < size + 1; k++ ) + { + A[ 1 ][ k ] -= ( alpha * A[ 3 ][ k ] + gamma * A[ 4 ][ k ] ); + } + if ( numactivep > 1 ) + { + if ( j == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ 1 ], 0, MPI_COMM_WORLD ); + } + else if ( j == numactivep - 1 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ numactivep - 2 ], 1, MPI_COMM_WORLD ); + } + else if ( j % 2 == 0 ) + { + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], 1, MPI_COMM_WORLD ); + MPI_Send( A[ 1 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], 0, MPI_COMM_WORLD ); + } + else + { + MPI_Recv( A[ 3 ], size + 1, MPI_DOUBLE, activep[ j - 1 ], 0, MPI_COMM_WORLD, &status ); + MPI_Recv( A[ 4 ], size + 1, MPI_DOUBLE, activep[ j + 1 ], 1, MPI_COMM_WORLD, &status ); + } + } + } + } + numactivep = 0; + for ( int j = activep[ 1 ]; j < totalnodes; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep ++ ] = j; + } + } + + /* Part 3 */ + //Part 3 - Back substitution + double * x = new double[ totalnodes ]; + for ( int j = 0; j < totalnodes; ++ j ) + { + x[ j ] = 0.0; + } + if ( mynode == activep[ 0 ] ) + { + x[ mynode ] = A[ 1 ][ size ] / A[ 1 ][ ( size - 1 ) / 2 ]; + } + double tmp; + for ( int i = log2( size + 1 ) - 3; i >= 0; -- i ) + { + tmp = x[ mynode ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, MPI_COMM_WORLD ); + numactivep = 0; + for ( int j = activep[ 0 ] - pow( 2, i ); j < totalnodes; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep ++ ] = j; + } + for ( int j = 0; j < numactivep; ++ j ) + { + if ( mynode == activep[ j ] ) + { + x[ mynode ] = A[ 1 ][ size ]; + for ( int k = 0; k < totalnodes; ++ k ) + { + if ( k != mynode ) + { + x[ mynode ] -= A[ 1 ][ 2 * k + 1 ] * x[ k ]; + } + } + x[ mynode ] = x[ mynode ] / A[ 1 ][ 2 * mynode + 1 ]; + } + } + } + + tmp = x[ mynode ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, MPI_COMM_WORLD ); + + /* Part 4 */ + //Part 4 - Solving for odd rows + + for ( int k = 0; k < totalnodes; ++ k ) + { + A[ 0 ][ size ] -= A[ 0 ][ 2 * k + 1 ] * x[ k ]; + A[ 2 ][ size ] -= A[ 2 ][ 2 * k + 1 ] * x[ k ]; + } + A[ 0 ][ size ] = A[ 0 ][ size ] / A[ 0 ][ 2 * mynode ]; + A[ 1 ][ size ] = x[ mynode ]; + A[ 2 ][ size ] = A[ 2 ][ size ] / A[ 2 ][ 2 * mynode + 2 ]; + + std::print( "totalnodes={}\n", totalnodes ); + + if ( mynode == 0 ) + { + std::print( "mynode = {}, x = ", mynode ); + for ( int j = 0; j < totalnodes; ++ j ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + } + else if ( mynode == ( totalnodes - 1 ) ) + { + std::print( "mynode = {}, x = ", mynode ); + for ( int j = 0; j < totalnodes; ++ j ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + + } + + Print( A, numrows, size + 1, "Matrix A Final" ); + + + delete[] activep; + for ( int i = 0; i < numrows; ++ i ) + { + delete[] A[ i ]; + } + delete[] A; + delete[] x; + MPI_Finalize(); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01f/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01f/CMakeLists.txt new file mode 100644 index 00000000..ade49a3f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01f/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp + LogFile.h LogFile.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01f/LogFile.cpp b/example/numerical/tdma/cpp/reference/parallel/01f/LogFile.cpp new file mode 100644 index 00000000..9222c0b9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01f/LogFile.cpp @@ -0,0 +1,140 @@ +#include "LogFile.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; +int Parallel::pid = 0; +int Parallel::nprocs = 1; + + +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/numerical/tdma/cpp/reference/parallel/01f/LogFile.h b/example/numerical/tdma/cpp/reference/parallel/01f/LogFile.h new file mode 100644 index 00000000..a5eda09f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01f/LogFile.h @@ -0,0 +1,34 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class Parallel +{ +public: + static int pid; + static int nprocs; +}; + +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/numerical/tdma/cpp/reference/parallel/01f/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01f/main.cpp new file mode 100644 index 00000000..8508c8ab --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01f/main.cpp @@ -0,0 +1,236 @@ +#include "mpi.h" +#include "LogFile.h" +import std; + +void PrintToScreen( double ** A, int numrows, int N, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{} ", A[ i ][ j ] ); + } + std::println(); + } +} + +void Print( double ** A, int numrows, int N, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + logFile << name << " = \n"; + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + logFile << A[ i ][ j ] << " "; + } + logFile << "\n"; + } +} + +int main( int argc, char ** argv ) +{ + //MPI initialization and both memory allocation and generation of the matrix A + int index; + int index1, index2; + double alpha, gamma; + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nprocs ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + + int N = (int)std::pow( 2, std::log2( Parallel::nprocs + 1 ) + 1 ) - 1; + std::print( "N={}", N ); + double ** A = new double * [ numrows ]; + for ( int i = 0; i < numrows; ++ i ) + { + A[ i ] = new double[ N + 1 ]; + for ( int j = 0; j < N + 1; ++ j ) + { + A[ i ][ j ] = 0.0; + } + } + std::print( "Parallel::pid={}, Parallel::nprocs={}, numrows={}, N={}\n", Parallel::pid, Parallel::nprocs, numrows, N ); + Print( A, numrows, N + 1, "Matrix A 0" ); + if ( Parallel::pid == 0 ) + { + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; + A[ 1 ][ 1 ] = -2.0; + A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; + A[ 2 ][ 2 ] = -2.0; + A[ 2 ][ 3 ] = 1.0; + } + else if ( Parallel::pid == ( Parallel::nprocs - 1 ) ) + { + index = 2 * Parallel::pid; + A[ 0 ][ index - 1 ] = 1.0; + A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + + index = 2 * Parallel::pid + 1; + A[ 1 ][ index - 1 ] = 1.0; + A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ N - 2 ] = 1.0; + A[ 2 ][ N - 1 ] = -2.0; + } + else + { + for ( int i = 0; i < 3; ++ i ) + { + index = 2 * Parallel::pid + i; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( int i = 0; i < 3; ++ i ) + { + A[ i ][ N ] = 2 * Parallel::pid + i; + } + int numactivep = Parallel::nprocs; + int * activep = new int[ Parallel::nprocs ]; + for ( int j = 0; j < numactivep; ++ j ) + { + activep[ j ] = j; + } + + for ( int j = 0; j < N + 1; ++ j ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + Print( A, numrows, N + 1, "Matrix A 1" ); + + /* Part 2 */ + //Cyclic reduction + + for ( int i = 0; i < log2( N + 1 ) - 1; ++ i ) + { + for ( int j = 0; j < numactivep; ++ j ) + { + if ( Parallel::pid == activep[ j ] ) + { + index1 = 2 * Parallel::pid + 1 - pow( 2, i ); + index2 = 2 * Parallel::pid + 1 + pow( 2, i ); + alpha = A[ 1 ][ index1 ] / A[ 3 ][ index1 ]; + gamma = A[ 1 ][ index2 ] / A[ 4 ][ index2 ]; + for ( int k = 0; k < N + 1; ++ k ) + { + A[ 1 ][ k ] -= ( alpha * A[ 3 ][ k ] + gamma * A[ 4 ][ k ] ); + } + if ( numactivep > 1 ) + { + if ( j == 0 ) + { + MPI_Send( A[ 1 ], N + 1, MPI_DOUBLE, activep[ 1 ], 0, MPI_COMM_WORLD ); + } + else if ( j == numactivep - 1 ) + { + MPI_Send( A[ 1 ], N + 1, MPI_DOUBLE, activep[ numactivep - 2 ], 1, MPI_COMM_WORLD ); + } + else if ( j % 2 == 0 ) + { + MPI_Send( A[ 1 ], N + 1, MPI_DOUBLE, activep[ j - 1 ], 1, MPI_COMM_WORLD ); + MPI_Send( A[ 1 ], N + 1, MPI_DOUBLE, activep[ j + 1 ], 0, MPI_COMM_WORLD ); + } + else + { + MPI_Recv( A[ 3 ], N + 1, MPI_DOUBLE, activep[ j - 1 ], 0, MPI_COMM_WORLD, &status ); + MPI_Recv( A[ 4 ], N + 1, MPI_DOUBLE, activep[ j + 1 ], 1, MPI_COMM_WORLD, &status ); + } + } + } + } + numactivep = 0; + for ( int j = activep[ 1 ]; j < Parallel::nprocs; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep ++ ] = j; + } + } + + /* Part 3 */ + //Part 3 - Back substitution + double * x = new double[ Parallel::nprocs ]; + for ( int j = 0; j < Parallel::nprocs; ++ j ) + { + x[ j ] = 0.0; + } + if ( Parallel::pid == activep[ 0 ] ) + { + x[ Parallel::pid ] = A[ 1 ][ N ] / A[ 1 ][ ( N - 1 ) / 2 ]; + } + double tmp; + for ( int i = log2( N + 1 ) - 3; i >= 0; -- i ) + { + tmp = x[ Parallel::pid ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, MPI_COMM_WORLD ); + numactivep = 0; + for ( int j = activep[ 0 ] - pow( 2, i ); j < Parallel::nprocs; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep ++ ] = j; + } + for ( int j = 0; j < numactivep; ++ j ) + { + if ( Parallel::pid == activep[ j ] ) + { + x[ Parallel::pid ] = A[ 1 ][ N ]; + for ( int k = 0; k < Parallel::nprocs; ++ k ) + { + if ( k != Parallel::pid ) + { + x[ Parallel::pid ] -= A[ 1 ][ 2 * k + 1 ] * x[ k ]; + } + } + x[ Parallel::pid ] = x[ Parallel::pid ] / A[ 1 ][ 2 * Parallel::pid + 1 ]; + } + } + } + + tmp = x[ Parallel::pid ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x, 1, MPI_DOUBLE, MPI_COMM_WORLD ); + + /* Part 4 */ + //Part 4 - Solving for odd rows + + for ( int k = 0; k < Parallel::nprocs; ++ k ) + { + A[ 0 ][ N ] -= A[ 0 ][ 2 * k + 1 ] * x[ k ]; + A[ 2 ][ N ] -= A[ 2 ][ 2 * k + 1 ] * x[ k ]; + } + A[ 0 ][ N ] = A[ 0 ][ N ] / A[ 0 ][ 2 * Parallel::pid ]; + A[ 1 ][ N ] = x[ Parallel::pid ]; + A[ 2 ][ N ] = A[ 2 ][ N ] / A[ 2 ][ 2 * Parallel::pid + 2 ]; + + std::print( "Parallel::nprocs={}\n", Parallel::nprocs ); + + if ( Parallel::pid == 0 ) + { + std::print( "Parallel::pid = {}, x = ", Parallel::pid ); + for ( int j = 0; j < Parallel::nprocs; ++ j ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + } + + Print( A, numrows, N + 1, "Matrix A Final" ); + + + delete[] activep; + for ( int i = 0; i < numrows; ++ i ) + { + delete[] A[ i ]; + } + delete[] A; + delete[] x; + MPI_Finalize(); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01g/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01g/CMakeLists.txt new file mode 100644 index 00000000..ade49a3f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01g/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp + LogFile.h LogFile.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01g/LogFile.cpp b/example/numerical/tdma/cpp/reference/parallel/01g/LogFile.cpp new file mode 100644 index 00000000..9222c0b9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01g/LogFile.cpp @@ -0,0 +1,140 @@ +#include "LogFile.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; +int Parallel::pid = 0; +int Parallel::nprocs = 1; + + +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/numerical/tdma/cpp/reference/parallel/01g/LogFile.h b/example/numerical/tdma/cpp/reference/parallel/01g/LogFile.h new file mode 100644 index 00000000..a5eda09f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01g/LogFile.h @@ -0,0 +1,34 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class Parallel +{ +public: + static int pid; + static int nprocs; +}; + +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/numerical/tdma/cpp/reference/parallel/01g/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01g/main.cpp new file mode 100644 index 00000000..649df227 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01g/main.cpp @@ -0,0 +1,244 @@ +#include "mpi.h" +#include "LogFile.h" +import std; + +void PrintToScreen( double ** A, int numrows, int N, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{} ", A[ i ][ j ] ); + } + std::println(); + } +} + +void Print( double ** A, int numrows, int N, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + logFile << name << " = \n"; + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + logFile << A[ i ][ j ] << " "; + } + logFile << "\n"; + } +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + logFile << name << " = \n"; + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + logFile << std::format( "{:2.0f} ", a[ i ][ j ] ); + } + logFile << "\n"; + } + logFile << "\n"; +} + +int main( int argc, char ** argv ) +{ + //MPI initialization and both memory allocation and generation of the matrix A + int index; + int index1, index2; + double alpha, gamma; + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nprocs ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + + int N = (int)std::pow( 2, std::log2( Parallel::nprocs + 1 ) + 1 ) - 1; + std::print( "N={}\n", N ); + std::print( "std::log2( Parallel::nprocs + 1 ) + 1 = {}\n", std::log2( Parallel::nprocs + 1 ) + 1 ); + std::vector> A( numrows ); + for ( int i = 0; i < A.size(); ++ i ) + { + A[ i ].resize( N + 1, 0.0 ); + } + std::print( "Parallel::pid={}, Parallel::nprocs={}, numrows={}, N={}\n", Parallel::pid, Parallel::nprocs, numrows, N ); + Print( A, "Matrix A 0" ); + if ( Parallel::pid == 0 ) + { + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; + A[ 1 ][ 1 ] = -2.0; + A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; + A[ 2 ][ 2 ] = -2.0; + A[ 2 ][ 3 ] = 1.0; + } + else if ( Parallel::pid == ( Parallel::nprocs - 1 ) ) + { + index = 2 * Parallel::pid; + A[ 0 ][ index - 1 ] = 1.0; + A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + + index = 2 * Parallel::pid + 1; + A[ 1 ][ index - 1 ] = 1.0; + A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ N - 2 ] = 1.0; + A[ 2 ][ N - 1 ] = -2.0; + } + else + { + for ( int i = 0; i < 3; ++ i ) + { + index = 2 * Parallel::pid + i; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( int i = 0; i < 3; ++ i ) + { + A[ i ][ N ] = 2 * Parallel::pid + i; + } + int numactivep = Parallel::nprocs; + std::vector activep( Parallel::nprocs ); + for ( int j = 0; j < numactivep; ++ j ) + { + activep[ j ] = j; + } + + for ( int j = 0; j < N + 1; ++ j ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + Print( A, "Matrix A 1" ); + + /* Part 2 */ + //Cyclic reduction + + for ( int i = 0; i < log2( N + 1 ) - 1; ++ i ) + { + for ( int j = 0; j < numactivep; ++ j ) + { + if ( Parallel::pid == activep[ j ] ) + { + index1 = 2 * Parallel::pid + 1 - pow( 2, i ); + index2 = 2 * Parallel::pid + 1 + pow( 2, i ); + alpha = A[ 1 ][ index1 ] / A[ 3 ][ index1 ]; + gamma = A[ 1 ][ index2 ] / A[ 4 ][ index2 ]; + for ( int k = 0; k < N + 1; ++ k ) + { + A[ 1 ][ k ] -= ( alpha * A[ 3 ][ k ] + gamma * A[ 4 ][ k ] ); + } + if ( numactivep > 1 ) + { + if ( j == 0 ) + { + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ 1 ], 0, MPI_COMM_WORLD ); + } + else if ( j == numactivep - 1 ) + { + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ numactivep - 2 ], 1, MPI_COMM_WORLD ); + } + else if ( j % 2 == 0 ) + { + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ j - 1 ], 1, MPI_COMM_WORLD ); + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ j + 1 ], 0, MPI_COMM_WORLD ); + } + else + { + MPI_Recv( A[ 3 ].data(), N + 1, MPI_DOUBLE, activep[ j - 1 ], 0, MPI_COMM_WORLD, &status ); + MPI_Recv( A[ 4 ].data(), N + 1, MPI_DOUBLE, activep[ j + 1 ], 1, MPI_COMM_WORLD, &status ); + } + } + } + } + numactivep = 0; + for ( int j = activep[ 1 ]; j < Parallel::nprocs; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep ++ ] = j; + } + } + + /* Part 3 */ + //Part 3 - Back substitution + std::vector x( Parallel::nprocs ); + for ( int j = 0; j < Parallel::nprocs; ++ j ) + { + x[ j ] = 0.0; + } + if ( Parallel::pid == activep[ 0 ] ) + { + x[ Parallel::pid ] = A[ 1 ][ N ] / A[ 1 ][ ( N - 1 ) / 2 ]; + } + double tmp; + std::print( "log2( N + 1 ) = {}\n", log2( N + 1 ) ); + std::print( "log2( N + 1 ) - 3 = {}\n", log2( N + 1 ) - 3 ); + for ( int i = log2( N + 1 ) - 3; i >= 0; -- i ) + { + tmp = x[ Parallel::pid ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x.data(), 1, MPI_DOUBLE, MPI_COMM_WORLD); + numactivep = 0; + for ( int j = activep[ 0 ] - pow( 2, i ); j < Parallel::nprocs; j = j + pow( 2, i + 1 ) ) + { + activep[ numactivep ++ ] = j; + } + for ( int j = 0; j < numactivep; ++ j ) + { + if ( Parallel::pid == activep[ j ] ) + { + x[ Parallel::pid ] = A[ 1 ][ N ]; + for ( int k = 0; k < Parallel::nprocs; ++ k ) + { + if ( k != Parallel::pid ) + { + x[ Parallel::pid ] -= A[ 1 ][ 2 * k + 1 ] * x[ k ]; + } + } + x[ Parallel::pid ] = x[ Parallel::pid ] / A[ 1 ][ 2 * Parallel::pid + 1 ]; + } + } + } + + tmp = x[ Parallel::pid ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x.data(), 1, MPI_DOUBLE, MPI_COMM_WORLD ); + + /* Part 4 */ + //Part 4 - Solving for odd rows + + for ( int k = 0; k < Parallel::nprocs; ++ k ) + { + A[ 0 ][ N ] -= A[ 0 ][ 2 * k + 1 ] * x[ k ]; + A[ 2 ][ N ] -= A[ 2 ][ 2 * k + 1 ] * x[ k ]; + } + A[ 0 ][ N ] = A[ 0 ][ N ] / A[ 0 ][ 2 * Parallel::pid ]; + A[ 1 ][ N ] = x[ Parallel::pid ]; + A[ 2 ][ N ] = A[ 2 ][ N ] / A[ 2 ][ 2 * Parallel::pid + 2 ]; + + std::print( "Parallel::nprocs={}\n", Parallel::nprocs ); + + if ( Parallel::pid == 0 ) + { + std::print( "Parallel::pid = {}, x = ", Parallel::pid ); + for ( int j = 0; j < Parallel::nprocs; ++ j ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + } + + //Print( A, numrows, N + 1, "Matrix A Final" ); + Print( A, "Matrix A Final" ); + + MPI_Finalize(); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01h/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01h/CMakeLists.txt new file mode 100644 index 00000000..ade49a3f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01h/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp + LogFile.h LogFile.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01h/LogFile.cpp b/example/numerical/tdma/cpp/reference/parallel/01h/LogFile.cpp new file mode 100644 index 00000000..9222c0b9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01h/LogFile.cpp @@ -0,0 +1,140 @@ +#include "LogFile.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; +int Parallel::pid = 0; +int Parallel::nprocs = 1; + + +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/numerical/tdma/cpp/reference/parallel/01h/LogFile.h b/example/numerical/tdma/cpp/reference/parallel/01h/LogFile.h new file mode 100644 index 00000000..a5eda09f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01h/LogFile.h @@ -0,0 +1,34 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class Parallel +{ +public: + static int pid; + static int nprocs; +}; + +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/numerical/tdma/cpp/reference/parallel/01h/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01h/main.cpp new file mode 100644 index 00000000..e0ac9abf --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01h/main.cpp @@ -0,0 +1,297 @@ +#include "mpi.h" +#include "LogFile.h" +import std; + +void PrintToScreen( double ** A, int numrows, int N, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{} ", A[ i ][ j ] ); + } + std::println(); + } +} + +void Print( double ** A, int numrows, int N, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + logFile << name << " = \n"; + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + logFile << A[ i ][ j ] << " "; + } + logFile << "\n"; + } +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + logFile << name << " = \n"; + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + logFile << std::format( "{:2.0f} ", a[ i ][ j ] ); + } + logFile << "\n"; + } + logFile << "\n"; +} + +template +void Print( std::vector & x, const std::string & name = "vector" ) +{ + logFile << name << " = \n"; + for ( auto v: x ) + { + logFile << std::format( "{:4} ", v ); + } + logFile << "\n"; +} + + +int main( int argc, char ** argv ) +{ + //Part 1 - MPI initialization + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nprocs ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + + int N = (int)std::pow( 2, std::log2( Parallel::nprocs + 1 ) + 1 ) - 1; + std::print( "N={}\n", N ); + std::print( "std::log2( Parallel::nprocs + 1 ) + 1 = {}\n", std::log2( Parallel::nprocs + 1 ) + 1 ); + std::vector> A( numrows ); + for ( int i = 0; i < A.size(); ++ i ) + { + A[ i ].resize( N + 1, 0.0 ); + } + std::print( "Parallel::pid={}, Parallel::nprocs={}, numrows={}, N={}\n", Parallel::pid, Parallel::nprocs, numrows, N ); + Print( A, "Matrix A 0" ); + if ( Parallel::pid == 0 ) + { + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; + A[ 1 ][ 1 ] = -2.0; + A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; + A[ 2 ][ 2 ] = -2.0; + A[ 2 ][ 3 ] = 1.0; + } + else if ( Parallel::pid == ( Parallel::nprocs - 1 ) ) + { + int index = 2 * Parallel::pid; + A[ 0 ][ index - 1 ] = 1.0; + A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + + index = 2 * Parallel::pid + 1; + A[ 1 ][ index - 1 ] = 1.0; + A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ N - 2 ] = 1.0; + A[ 2 ][ N - 1 ] = -2.0; + } + else + { + for ( int i = 0; i < 3; ++ i ) + { + int index = 2 * Parallel::pid + i; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( int i = 0; i < 3; ++ i ) + { + A[ i ][ N ] = 2 * Parallel::pid + i; + } + int numactivep = Parallel::nprocs; + std::vector activep( Parallel::nprocs ); + for ( int j = 0; j < numactivep; ++ j ) + { + activep[ j ] = j; + } + + for ( int j = 0; j < N + 1; ++ j ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + Print( A, "Matrix A 1" ); + + //Part 2 - Cyclic reduction + + for ( int level = 0; level < std::log2( N + 1 ) - 1; ++ level ) + { + logFile << "Cyclic reduction level = " << level << "\n"; + int offset = std::pow( 2, level ); + int step = std::pow( 2, level + 1 ); + logFile << "offset = " << offset << " step = " << step << "\n"; + for ( int j = 0; j < numactivep; ++ j ) + { + logFile << "j = " << j << " numactivep = " << numactivep << "\n"; + if ( Parallel::pid == activep[ j ] ) + { + logFile << " Parallel::pid = " << Parallel::pid << " activep[ j ] = " << activep[ j ] << "\n"; + + int index1 = 2 * Parallel::pid + 1 - offset; + int index2 = 2 * Parallel::pid + 1 + offset; + logFile << " index1 = " << index1 << " index2 = " << index2 << "\n"; + + double alpha = A[ 1 ][ index1 ] / A[ 3 ][ index1 ]; + double gamma = A[ 1 ][ index2 ] / A[ 4 ][ index2 ]; + for ( int k = 0; k < N + 1; ++ k ) + { + A[ 1 ][ k ] -= ( alpha * A[ 3 ][ k ] + gamma * A[ 4 ][ k ] ); + } + if ( numactivep > 1 ) + { + if ( j == 0 ) + { + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ 1 ], 0, MPI_COMM_WORLD ); + } + else if ( j == numactivep - 1 ) + { + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ numactivep - 2 ], 1, MPI_COMM_WORLD ); + } + else if ( j % 2 == 0 ) + { + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ j - 1 ], 1, MPI_COMM_WORLD ); + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ j + 1 ], 0, MPI_COMM_WORLD ); + } + else + { + MPI_Recv( A[ 3 ].data(), N + 1, MPI_DOUBLE, activep[ j - 1 ], 0, MPI_COMM_WORLD, &status ); + MPI_Recv( A[ 4 ].data(), N + 1, MPI_DOUBLE, activep[ j + 1 ], 1, MPI_COMM_WORLD, &status ); + } + } + } + } + + logFile << "activep[ 1 ] = " << activep[ 1 ] << " numactivep = " << numactivep; + logFile << " Parallel::nprocs = " << Parallel::nprocs << "\n"; + logFile << "Cyclic reduction level = " << level << "\n"; + Print( activep, "Cyclic reduction vector activep 000" ); + + numactivep = 0; + for ( int j = activep[ 1 ]; j < Parallel::nprocs; j = j + step ) + { + logFile << "j = " << j << " numactivep = " << numactivep << "\n"; + activep[ numactivep ++ ] = j; + } + logFile << "Final numactivep = " << numactivep << "\n"; + Print( activep, "Cyclic reduction vector activep 111" ); + } + + Print( A, "Matrix A 2" ); + + //Part 3 - Back substitution + logFile << "Back substitution\n"; + std::vector x( Parallel::nprocs, 0.0 ); + if ( Parallel::pid == activep[ 0 ] ) + { + logFile << "N = " << N << ";( N - 1 ) / 2 = " << ( N - 1 ) / 2 << "\n"; + x[ Parallel::pid ] = A[ 1 ][ N ] / A[ 1 ][ ( N - 1 ) / 2 ]; + } + double tmp; + std::print( "std::log2( N + 1 ) = {}\n", std::log2( N + 1 ) ); + std::print( "std::log2( N + 1 ) - 3 = {}\n", std::log2( N + 1 ) - 3 ); + std::print( "std::log2( N + 1 ) - 2 = {}\n", std::log2( N + 1 ) - 2 ); + Print( x, "vector x 000" ); + for ( int level = std::log2( N + 1 ) - 3; level >= 0; -- level ) + { + logFile << "Back substitution level = " << level << "\n"; + int offset = std::pow( 2, level ); + int step = std::pow( 2, level + 1 ); + + logFile << "offset = " << offset << " step = " << step << "\n"; + + tmp = x[ Parallel::pid ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x.data(), 1, MPI_DOUBLE, MPI_COMM_WORLD ); + Print( x, "vector x 111" ); + logFile << "activep[ 0 ] = " << activep[ 0 ] << " activep[ 0 ] - offset = " << activep[ 0 ] - offset; + logFile << " Parallel::nprocs = " << Parallel::nprocs << "\n"; + Print( activep, "vector activep 000" ); + numactivep = 0; + for ( int j = activep[ 0 ] - offset; j < Parallel::nprocs; j = j + step ) + { + logFile << "j = " << j << " numactivep = " << numactivep << "\n"; + logFile << "000 activep[" << numactivep << "] = " << activep[ numactivep ] << "\n"; + activep[ numactivep ++ ] = j; + logFile << "111 activep[" << numactivep << "] = " << activep[ numactivep ] << "\n"; + } + logFile << "numactivep = " << numactivep << "\n"; + Print( activep, "vector activep 111" ); + + for ( int j = 0; j < numactivep; ++ j ) + { + logFile << "j = " << j << " numactivep = " << numactivep; + logFile << "activep[" << j << "] = " << activep[ j ] << " Parallel::pid = " << Parallel::pid << "\n"; + + if ( Parallel::pid == activep[ j ] ) + { + logFile << "000 x[" << Parallel::pid << "] = " << x[ Parallel::pid ] << "\n"; + x[ Parallel::pid ] = A[ 1 ][ N ]; + logFile << "111 x[" << Parallel::pid << "] = " << x[ Parallel::pid ] << "\n"; + for ( int k = 0; k < Parallel::nprocs; ++ k ) + { + if ( k != Parallel::pid ) + { + x[ Parallel::pid ] -= A[ 1 ][ 2 * k + 1 ] * x[ k ]; + } + } + logFile << "222 x[" << Parallel::pid << "] = " << x[ Parallel::pid ] << "\n"; + logFile << "Parallel::pid = "<< Parallel::pid << "; 2 * Parallel::pid + 1 = " << 2 * Parallel::pid + 1 << "\n"; + logFile << "A[ 1 ][" << 2 * Parallel::pid + 1 << "] = "<< A[ 1 ][ 2 * Parallel::pid + 1 ] << "\n"; + + x[ Parallel::pid ] = x[ Parallel::pid ] / A[ 1 ][ 2 * Parallel::pid + 1 ]; + logFile << "333 x[" << Parallel::pid << "] = " << x[ Parallel::pid ] << "\n"; + } + } + Print( x, "vector x 222" ); + } + + tmp = x[ Parallel::pid ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x.data(), 1, MPI_DOUBLE, MPI_COMM_WORLD ); + + //Part 4 - Solving for odd rows + + for ( int k = 0; k < Parallel::nprocs; ++ k ) + { + A[ 0 ][ N ] -= A[ 0 ][ 2 * k + 1 ] * x[ k ]; + A[ 2 ][ N ] -= A[ 2 ][ 2 * k + 1 ] * x[ k ]; + } + A[ 0 ][ N ] = A[ 0 ][ N ] / A[ 0 ][ 2 * Parallel::pid ]; + A[ 1 ][ N ] = x[ Parallel::pid ]; + A[ 2 ][ N ] = A[ 2 ][ N ] / A[ 2 ][ 2 * Parallel::pid + 2 ]; + + std::print( "Parallel::nprocs={}\n", Parallel::nprocs ); + Print( x, "vector x" ); + + if ( Parallel::pid == 0 ) + { + std::print( "Parallel::pid = {}, x = ", Parallel::pid ); + for ( int j = 0; j < Parallel::nprocs; ++ j ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + } + + Print( A, "Matrix A Final" ); + + MPI_Finalize(); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/01i/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/01i/CMakeLists.txt new file mode 100644 index 00000000..ade49a3f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01i/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp + LogFile.h LogFile.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/01i/LogFile.cpp b/example/numerical/tdma/cpp/reference/parallel/01i/LogFile.cpp new file mode 100644 index 00000000..9222c0b9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01i/LogFile.cpp @@ -0,0 +1,140 @@ +#include "LogFile.h" +#include +#include + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif + +LogFile logFile; +int Parallel::pid = 0; +int Parallel::nprocs = 1; + + +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/numerical/tdma/cpp/reference/parallel/01i/LogFile.h b/example/numerical/tdma/cpp/reference/parallel/01i/LogFile.h new file mode 100644 index 00000000..a5eda09f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01i/LogFile.h @@ -0,0 +1,34 @@ +#pragma once +#include + +void OpenLogFile( int logFileIndex, std::fstream & file ); +void CloseLogFile( std::fstream & file ); +class LogFile; +extern LogFile logFile; + +class Parallel +{ +public: + static int pid; + static int nprocs; +}; + +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/numerical/tdma/cpp/reference/parallel/01i/main.cpp b/example/numerical/tdma/cpp/reference/parallel/01i/main.cpp new file mode 100644 index 00000000..d241f9ba --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/01i/main.cpp @@ -0,0 +1,300 @@ +#include "mpi.h" +#include "LogFile.h" +import std; + +void PrintToScreen( double ** A, int numrows, int N, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{} ", A[ i ][ j ] ); + } + std::println(); + } +} + +void Print( double ** A, int numrows, int N, const std::string & name = "matrix" ) +{ + std::print( "{} = \n", name ); + logFile << name << " = \n"; + for ( int i = 0; i < numrows; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + logFile << A[ i ][ j ] << " "; + } + logFile << "\n"; + } +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + logFile << name << " = \n"; + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + logFile << std::format( "{:5.2f} ", a[ i ][ j ] ); + } + logFile << "\n"; + } + logFile << "\n"; +} + +template +void Print( std::vector & x, const std::string & name = "vector" ) +{ + logFile << name << " = \n"; + for ( auto v: x ) + { + logFile << std::format( "{:4} ", v ); + } + logFile << "\n"; +} + + +int main( int argc, char ** argv ) +{ + //Part 1 - MPI initialization + const int numrows = 5; + + MPI_Status status; + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &Parallel::nprocs ); + MPI_Comm_rank( MPI_COMM_WORLD, &Parallel::pid ); + + int N = (int)std::pow( 2, std::log2( Parallel::nprocs + 1 ) + 1 ) - 1; + std::print( "N={}\n", N ); + std::print( "std::log2( Parallel::nprocs + 1 ) + 1 = {}\n", std::log2( Parallel::nprocs + 1 ) + 1 ); + std::vector> A( numrows ); + for ( int i = 0; i < A.size(); ++ i ) + { + A[ i ].resize( N + 1, 0.0 ); + } + std::print( "Parallel::pid={}, Parallel::nprocs={}, numrows={}, N={}\n", Parallel::pid, Parallel::nprocs, numrows, N ); + Print( A, "Matrix A 0" ); + if ( Parallel::pid == 0 ) + { + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ 1 ][ 0 ] = 1.0; + A[ 1 ][ 1 ] = -2.0; + A[ 1 ][ 2 ] = 1.0; + A[ 2 ][ 1 ] = 1.0; + A[ 2 ][ 2 ] = -2.0; + A[ 2 ][ 3 ] = 1.0; + } + else if ( Parallel::pid == ( Parallel::nprocs - 1 ) ) + { + int index = 2 * Parallel::pid; + A[ 0 ][ index - 1 ] = 1.0; + A[ 0 ][ index ] = -2.0; + A[ 0 ][ index + 1 ] = 1.0; + + index = 2 * Parallel::pid + 1; + A[ 1 ][ index - 1 ] = 1.0; + A[ 1 ][ index ] = -2.0; + A[ 1 ][ index + 1 ] = 1.0; + A[ 2 ][ N - 2 ] = 1.0; + A[ 2 ][ N - 1 ] = -2.0; + } + else + { + for ( int i = 0; i < 3; ++ i ) + { + int index = 2 * Parallel::pid + i; + A[ i ][ index - 1 ] = 1.0; + A[ i ][ index ] = -2.0; + A[ i ][ index + 1 ] = 1.0; + } + } + for ( int i = 0; i < 3; ++ i ) + { + A[ i ][ N ] = 2 * Parallel::pid + i; + } + int numactivep = Parallel::nprocs; + std::vector activep( Parallel::nprocs ); + for ( int j = 0; j < numactivep; ++ j ) + { + activep[ j ] = j; + } + + for ( int j = 0; j < N + 1; ++ j ) + { + A[ 3 ][ j ] = A[ 0 ][ j ]; + A[ 4 ][ j ] = A[ 2 ][ j ]; + } + Print( A, "Matrix A 1" ); + + //Part 2 - Cyclic reduction + + for ( int level = 0; level < std::log2( N + 1 ) - 1; ++ level ) + { + logFile << "Cyclic reduction level = " << level << "\n"; + int offset = std::pow( 2, level ); + int step = std::pow( 2, level + 1 ); + logFile << "offset = " << offset << " step = " << step << "\n"; + logFile << "numactivep = " << numactivep << "\n"; + for ( int j = 0; j < numactivep; ++ j ) + { + logFile << "j = " << j << " numactivep = " << numactivep << "\n"; + if ( Parallel::pid == activep[ j ] ) + { + logFile << " Parallel::pid = " << Parallel::pid << " activep[ j ] = " << activep[ j ] << "\n"; + + int index1 = 2 * Parallel::pid + 1 - offset; + int index2 = 2 * Parallel::pid + 1 + offset; + logFile << " index1 = " << index1 << " index2 = " << index2 << "\n"; + + double alpha = A[ 1 ][ index1 ] / A[ 3 ][ index1 ]; + double gamma = A[ 1 ][ index2 ] / A[ 4 ][ index2 ]; + for ( int k = 0; k < N + 1; ++ k ) + { + A[ 1 ][ k ] -= ( alpha * A[ 3 ][ k ] + gamma * A[ 4 ][ k ] ); + } + if ( numactivep > 1 ) + { + if ( j == 0 ) + { + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ 1 ], 0, MPI_COMM_WORLD ); + } + else if ( j == numactivep - 1 ) + { + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ numactivep - 2 ], 1, MPI_COMM_WORLD ); + } + else if ( j % 2 == 0 ) + { + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ j - 1 ], 1, MPI_COMM_WORLD ); + MPI_Send( A[ 1 ].data(), N + 1, MPI_DOUBLE, activep[ j + 1 ], 0, MPI_COMM_WORLD ); + } + else + { + MPI_Recv( A[ 3 ].data(), N + 1, MPI_DOUBLE, activep[ j - 1 ], 0, MPI_COMM_WORLD, &status ); + MPI_Recv( A[ 4 ].data(), N + 1, MPI_DOUBLE, activep[ j + 1 ], 1, MPI_COMM_WORLD, &status ); + } + } + } + } + + logFile << "activep[ 1 ] = " << activep[ 1 ] << " numactivep = " << numactivep; + logFile << " Parallel::nprocs = " << Parallel::nprocs << "\n"; + logFile << "Cyclic reduction level = " << level << "\n"; + Print( activep, "Cyclic reduction vector activep 000" ); + + numactivep = 0; + for ( int j = activep[ 1 ]; j < Parallel::nprocs; j = j + step ) + { + logFile << "j = " << j << " numactivep = " << numactivep << "\n"; + activep[ numactivep ++ ] = j; + } + logFile << "Final numactivep = " << numactivep << "\n"; + Print( activep, "Cyclic reduction vector activep 111" ); + } + + Print( A, "Matrix A 2" ); + + //Part 3 - Back substitution + logFile << "Back substitution\n"; + std::vector x( Parallel::nprocs, 0.0 ); + logFile << "Parallel::pid = " << Parallel::pid << " activep[ 0 ] = " << activep[ 0 ] << "\n"; + if ( Parallel::pid == activep[ 0 ] ) + { + logFile << "N = " << N << ";( N - 1 ) / 2 = " << ( N - 1 ) / 2 << "\n"; + x[ Parallel::pid ] = A[ 1 ][ N ] / A[ 1 ][ ( N - 1 ) / 2 ]; + } + double tmp; + std::print( "std::log2( N + 1 ) = {}\n", std::log2( N + 1 ) ); + std::print( "std::log2( N + 1 ) - 3 = {}\n", std::log2( N + 1 ) - 3 ); + std::print( "std::log2( N + 1 ) - 2 = {}\n", std::log2( N + 1 ) - 2 ); + Print( x, "vector x 000" ); + for ( int level = std::log2( N + 1 ) - 3; level >= 0; -- level ) + { + logFile << "Back substitution level = " << level << "\n"; + int offset = std::pow( 2, level ); + int step = std::pow( 2, level + 1 ); + + logFile << "offset = " << offset << " step = " << step << "\n"; + + tmp = x[ Parallel::pid ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x.data(), 1, MPI_DOUBLE, MPI_COMM_WORLD ); + Print( x, "vector x 111" ); + logFile << "activep[ 0 ] = " << activep[ 0 ] << " activep[ 0 ] - offset = " << activep[ 0 ] - offset; + logFile << " Parallel::nprocs = " << Parallel::nprocs << "\n"; + Print( activep, "vector activep 000" ); + numactivep = 0; + for ( int j = activep[ 0 ] - offset; j < Parallel::nprocs; j = j + step ) + { + logFile << "j = " << j << " numactivep = " << numactivep << "\n"; + logFile << "000 activep[" << numactivep << "] = " << activep[ numactivep ] << "\n"; + activep[ numactivep ++ ] = j; + logFile << "111 activep[" << numactivep << "] = " << activep[ numactivep ] << "\n"; + } + logFile << "numactivep = " << numactivep << "\n"; + Print( activep, "vector activep 111" ); + + for ( int j = 0; j < numactivep; ++ j ) + { + logFile << "j = " << j << " numactivep = " << numactivep; + logFile << " activep[" << j << "] = " << activep[ j ] << " Parallel::pid = " << Parallel::pid << "\n"; + + if ( Parallel::pid == activep[ j ] ) + { + logFile << "000 x[" << Parallel::pid << "] = " << x[ Parallel::pid ] << "\n"; + x[ Parallel::pid ] = A[ 1 ][ N ]; + logFile << "111 x[" << Parallel::pid << "] = " << x[ Parallel::pid ] << "\n"; + for ( int k = 0; k < Parallel::nprocs; ++ k ) + { + if ( k != Parallel::pid ) + { + x[ Parallel::pid ] -= A[ 1 ][ 2 * k + 1 ] * x[ k ]; + } + } + logFile << "222 x[" << Parallel::pid << "] = " << x[ Parallel::pid ] << "\n"; + logFile << "Parallel::pid = "<< Parallel::pid << "; 2 * Parallel::pid + 1 = " << 2 * Parallel::pid + 1 << "\n"; + logFile << "A[ 1 ][" << 2 * Parallel::pid + 1 << "] = "<< A[ 1 ][ 2 * Parallel::pid + 1 ] << "\n"; + + x[ Parallel::pid ] = x[ Parallel::pid ] / A[ 1 ][ 2 * Parallel::pid + 1 ]; + logFile << "333 x[" << Parallel::pid << "] = " << x[ Parallel::pid ] << "\n"; + } + } + Print( x, "vector x 222" ); + } + + tmp = x[ Parallel::pid ]; + MPI_Allgather( &tmp, 1, MPI_DOUBLE, x.data(), 1, MPI_DOUBLE, MPI_COMM_WORLD ); + + //Part 4 - Solving for odd rows + + for ( int k = 0; k < Parallel::nprocs; ++ k ) + { + A[ 0 ][ N ] -= A[ 0 ][ 2 * k + 1 ] * x[ k ]; + A[ 2 ][ N ] -= A[ 2 ][ 2 * k + 1 ] * x[ k ]; + } + + A[ 0 ][ N ] = A[ 0 ][ N ] / A[ 0 ][ 2 * Parallel::pid ]; + A[ 1 ][ N ] = x[ Parallel::pid ]; + A[ 2 ][ N ] = A[ 2 ][ N ] / A[ 2 ][ 2 * Parallel::pid + 2 ]; + + std::print( "Parallel::nprocs={}\n", Parallel::nprocs ); + Print( x, "vector x" ); + + if ( Parallel::pid == 0 ) + { + std::print( "Parallel::pid = {}, x = ", Parallel::pid ); + for ( int j = 0; j < Parallel::nprocs; ++ j ) + { + std::print( "{} ", x[ j ] ); + } + std::println(); + } + + Print( A, "Matrix A Final" ); + + MPI_Finalize(); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/01/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/printinfo/01/CMakeLists.txt new file mode 100644 index 00000000..c7a713a9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/01/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/01/main.cpp b/example/numerical/tdma/cpp/reference/parallel/printinfo/01/main.cpp new file mode 100644 index 00000000..485dc2ac --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/01/main.cpp @@ -0,0 +1,48 @@ +import std; + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:2.0f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +int main( int argc, char ** argv ) +{ + int N = 15; + int NProc = 7; + std::vector> A; + A.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + } + for ( int iProc = 0; iProc < NProc; ++ iProc ) + { + //int loc = 2 * iProc + 1; //1,3,5,7,9,11,13 + int loc = 2 * iProc; //0,2,4,6,8,10,12 + for ( int i = 0; i < 3; ++ i ) + { + int iloc = loc + i; + if ( ( iloc - 1 ) >= 0 ) + { + A[ iloc ][ iloc - 1 ] = 1.0; + } + A[ iloc ][ iloc ] = -2.0; + if ( ( iloc + 1 ) < N ) + { + A[ iloc ][ iloc + 1 ] = 1.0; + } + } + } + + Print( A, "matrix A" ); + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/01a/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/printinfo/01a/CMakeLists.txt new file mode 100644 index 00000000..c7a713a9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/01a/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/01a/main.cpp b/example/numerical/tdma/cpp/reference/parallel/printinfo/01a/main.cpp new file mode 100644 index 00000000..9e3dd762 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/01a/main.cpp @@ -0,0 +1,94 @@ +import std; + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::print( "{:2.0f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void SetMatrixValue( int N, int nProc ) +{ + std::vector> A; + A.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + } + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + //int loc = 2 * iProc + 1; //1,3,5,7,9,11,13 + int loc = 2 * iProc; //0,2,4,6,8,10,12 + for ( int i = 0; i < 3; ++ i ) + { + int iloc = loc + i; + if ( ( iloc - 1 ) >= 0 ) + { + A[ iloc ][ iloc - 1 ] = 1.0; + } + A[ iloc ][ iloc ] = -2.0; + if ( ( iloc + 1 ) < N ) + { + A[ iloc ][ iloc + 1 ] = 1.0; + } + } + } + + Print( A, "matrix A" ); +} + +void SetMatrixValueNew( int N, int nProc ) +{ + std::vector>> AList; + AList.resize( nProc ); + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nRow = 3; + AList[ iProc ].resize( nRow ); + for ( int i = 0; i < nRow; ++ i ) + { + AList[ iProc ][ i ].resize( N ); + } + + } + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::vector> & A = AList[ iProc ]; + //int loc = 2 * iProc + 1; //1,3,5,7,9,11,13 + int loc = 2 * iProc; //0,2,4,6,8,10,12 + for ( int i = 0; i < 3; ++ i ) + { + int iloc = loc + i; + if ( ( iloc - 1 ) >= 0 ) + { + A[ i ][ iloc - 1 ] = 1.0; + } + A[ i ][ iloc ] = -2.0; + if ( ( iloc + 1 ) < N ) + { + A[ i ][ iloc + 1 ] = 1.0; + } + } + std::print("iProc={}\n", iProc ); + Print( A, "matrix A" ); + } +} + +int main( int argc, char ** argv ) +{ + int N = 15; + int nProc = 7; + + SetMatrixValue( N, nProc ); + SetMatrixValueNew( N, nProc ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/01b/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/printinfo/01b/CMakeLists.txt new file mode 100644 index 00000000..c7a713a9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/01b/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/01b/main.cpp b/example/numerical/tdma/cpp/reference/parallel/printinfo/01b/main.cpp new file mode 100644 index 00000000..16bd7b9d --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/01b/main.cpp @@ -0,0 +1,107 @@ +import std; +template +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::print( "{:2.0f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void SetMatrixValue( int N, int nProc ) +{ + std::vector> A; + A.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + } + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + //int loc = 2 * iProc + 1; //1,3,5,7,9,11,13 + int loc = 2 * iProc; //0,2,4,6,8,10,12 + for ( int i = 0; i < 3; ++ i ) + { + int iloc = loc + i; + if ( ( iloc - 1 ) >= 0 ) + { + A[ iloc ][ iloc - 1 ] = 1.0; + } + A[ iloc ][ iloc ] = -2.0; + if ( ( iloc + 1 ) < N ) + { + A[ iloc ][ iloc + 1 ] = 1.0; + } + } + } + + Print( A, "matrix A" ); +} + +void SetMatrixValueNew( int N, int nProc ) +{ + std::vector>> AList; + AList.resize( nProc ); + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nRow = 3; + AList[ iProc ].resize( nRow ); + for ( int i = 0; i < nRow; ++ i ) + { + AList[ iProc ][ i ].resize( N ); + } + + } + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::vector> & A = AList[ iProc ]; + //int loc = 2 * iProc + 1; //1,3,5,7,9,11,13 + int loc = 2 * iProc; //0,2,4,6,8,10,12 + std::vector global_locs( 3 ); + for ( int i = 0; i < 3; ++ i ) + { + int iloc = loc + i; + global_locs[ i ] = iloc; + if ( ( iloc - 1 ) >= 0 ) + { + A[ i ][ iloc - 1 ] = 1.0; + } + A[ i ][ iloc ] = -2.0; + if ( ( iloc + 1 ) < N ) + { + A[ i ][ iloc + 1 ] = 1.0; + } + } + std::print("iProc={}\n", iProc ); + Print( global_locs, "global_locs" ); + Print( A, "matrix A" ); + } +} + +int main( int argc, char ** argv ) +{ + int N = 15; + int nProc = 7; + + SetMatrixValue( N, nProc ); + SetMatrixValueNew( N, nProc ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/01c/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/printinfo/01c/CMakeLists.txt new file mode 100644 index 00000000..c7a713a9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/01c/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/01c/main.cpp b/example/numerical/tdma/cpp/reference/parallel/printinfo/01c/main.cpp new file mode 100644 index 00000000..3a395982 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/01c/main.cpp @@ -0,0 +1,109 @@ +import std; +template +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::print( "{:2.0f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void SetMatrixValue( int N, int nProc ) +{ + std::vector> A; + A.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + } + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + //int loc = 2 * iProc + 1; //1,3,5,7,9,11,13 + int loc = 2 * iProc; //0,2,4,6,8,10,12 + for ( int i = 0; i < 3; ++ i ) + { + int iloc = loc + i; + if ( ( iloc - 1 ) >= 0 ) + { + A[ iloc ][ iloc - 1 ] = 1.0; + } + A[ iloc ][ iloc ] = -2.0; + if ( ( iloc + 1 ) < N ) + { + A[ iloc ][ iloc + 1 ] = 1.0; + } + } + } + + Print( A, "matrix A" ); +} + +void SetMatrixValueNew( int N, int nProc ) +{ + std::vector>> AList; + AList.resize( nProc ); + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nRow = 3; + AList[ iProc ].resize( nRow ); + for ( int i = 0; i < nRow; ++ i ) + { + AList[ iProc ][ i ].resize( N ); + } + + } + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::vector> & A = AList[ iProc ]; + //int loc = 2 * iProc + 1; //1,3,5,7,9,11,13 + int loc = 2 * iProc; //0,2,4,6,8,10,12 + std::vector global_locs( 3 ); + for ( int i = 0; i < 3; ++ i ) + { + int iloc = loc + i; + global_locs[ i ] = iloc; + if ( ( iloc - 1 ) >= 0 ) + { + A[ i ][ iloc - 1 ] = 1.0; + } + A[ i ][ iloc ] = -2.0; + if ( ( iloc + 1 ) < N ) + { + A[ i ][ iloc + 1 ] = 1.0; + } + } + std::print("iProc={}\n", iProc ); + Print( global_locs, "global_locs" ); + Print( A, "matrix A" ); + } +} + +int main( int argc, char ** argv ) +{ + int p = 3; + int N = std::pow( 2, p ) - 1; + int nProc = ( N + 1 ) / 2 - 1; + std::print( "p={},nProc={},N={}\n", p, nProc, N ); + + SetMatrixValue( N, nProc ); + SetMatrixValueNew( N, nProc ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/02/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/printinfo/02/CMakeLists.txt new file mode 100644 index 00000000..c7a713a9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/02/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/02/main.cpp b/example/numerical/tdma/cpp/reference/parallel/printinfo/02/main.cpp new file mode 100644 index 00000000..b41e9654 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/02/main.cpp @@ -0,0 +1,12 @@ +import std; + +int main( int argc, char ** argv ) +{ + for ( int nprocs = 1; nprocs <= 7; ++ nprocs ) + { + int N = (int)std::pow( 2, std::log2( nprocs + 1 ) + 1 ) - 1; + std::print( "nprocs = {}, N = {:4}, (N-1)/2 = {}\n", nprocs, N, ( N - 1 ) / 2 ); + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/02a/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/printinfo/02a/CMakeLists.txt new file mode 100644 index 00000000..c7a713a9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/02a/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/02a/main.cpp b/example/numerical/tdma/cpp/reference/parallel/printinfo/02a/main.cpp new file mode 100644 index 00000000..b9adc607 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/02a/main.cpp @@ -0,0 +1,12 @@ +import std; + +int main( int argc, char ** argv ) +{ + for ( int p = 0; p <= 10; ++ p ) + { + int N = std::pow( 2, p ) - 1; + std::print( "p = {:3}, N = {:5}\n", p, N ); + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/02b/CMakeLists.txt b/example/numerical/tdma/cpp/reference/parallel/printinfo/02b/CMakeLists.txt new file mode 100644 index 00000000..c7a713a9 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/02b/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) +set ( PRJ_COMPILE_DEFINITIONS ) +set ( PRJ_LIBRARIES ) +set ( PRJ_INCLUDE_DIRS ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +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} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/parallel/printinfo/02b/main.cpp b/example/numerical/tdma/cpp/reference/parallel/printinfo/02b/main.cpp new file mode 100644 index 00000000..f55a588d --- /dev/null +++ b/example/numerical/tdma/cpp/reference/parallel/printinfo/02b/main.cpp @@ -0,0 +1,13 @@ +import std; + +int main( int argc, char ** argv ) +{ + for ( int p = 0; p <= 10; ++ p ) + { + int N = std::pow( 2, p ) - 1; + int nprocs = ( N + 1 ) / 2 - 1; + std::print( "p = {:3}, N = {:5}, nprocs = {:5}\n", p, N, nprocs ); + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01/main.cpp b/example/numerical/tdma/cpp/reference/serial/01/main.cpp new file mode 100644 index 00000000..f1a41f9f --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01/main.cpp @@ -0,0 +1,47 @@ +import std; + +const int size = 15; + +int main( int argc, char ** argv ) +{ + int j,k; + int index1, index2, offset; + double alpha, gamma; + /* Part 1 */ + double * x = new double[ size ]; + for ( int i = 0; i < size; ++ i ) + { + x[ i ] = 0.0; + } + double * F = new double[ size ]; + double ** A = new double * [ size ]; + for ( int i = 0; i < size; ++ i ) + { + A[ i ] = new double[ size ]; + for ( int j = 0; j < size; ++ j ) + { + A[ i ][ j ] = 0.0; + } + F[ i ] = (double)i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ size - 1 ][ size - 2 ] = 1.0; + A[ size - 1 ][ size - 1 ] = -2.0; + for ( int i = 1; i < size - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + delete [] x; + delete [] F; + for ( int i = 0; i < size; ++ i ) + { + delete[] A[ i ]; + } + delete [] A; + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01a/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01a/main.cpp b/example/numerical/tdma/cpp/reference/serial/01a/main.cpp new file mode 100644 index 00000000..09005ca5 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01a/main.cpp @@ -0,0 +1,66 @@ +import std; + +const int size = 15; + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + double * x = new double[ size ]; + for ( int i = 0; i < size; ++ i ) + { + x[ i ] = 0.0; + } + double * F = new double[ size ]; + double ** A = new double * [ size ]; + for ( int i = 0; i < size; ++ i ) + { + A[ i ] = new double[ size ]; + for ( int j = 0; j < size; ++ j ) + { + A[ i ][ j ] = 0.0; + } + F[ i ] = (double)i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ size - 1 ][ size - 2 ] = 1.0; + A[ size - 1 ][ size - 1 ] = -2.0; + for ( int i = 1; i < size - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + //Cyclic reduction + for ( int i = 0; i < std::log2( size + 1 ) - 1; ++ i ) + { + std::print( "i={}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + double alpha = A[ j ][ index1 ] / A[ index1 ][ index1 ]; + double gamma = A[ j ][ index2 ] / A[ index2 ][ index2 ]; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + for ( int k = 0; k < size; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ index1 ][ k ] + gamma * A[ index2 ][ k ] ); + std::print( "({},{})", j, k ); + } + std::println(); + F[ j ] -= ( alpha * F[ index1 ] + gamma * F[ index2 ] ); + } + } + + delete [] x; + delete [] F; + for ( int i = 0; i < size; ++ i ) + { + delete [] A[ i ]; + } + delete [] A; + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01b/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01b/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01b/main.cpp b/example/numerical/tdma/cpp/reference/serial/01b/main.cpp new file mode 100644 index 00000000..47cc2b44 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01b/main.cpp @@ -0,0 +1,101 @@ +import std; + +const int size = 15; + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + double * x = new double[ size ]; + for ( int i = 0; i < size; ++ i ) + { + x[ i ] = 0.0; + } + double * F = new double[ size ]; + double ** A = new double * [ size ]; + for ( int i = 0; i < size; ++ i ) + { + A[ i ] = new double[ size ]; + for ( int j = 0; j < size; ++ j ) + { + A[ i ][ j ] = 0.0; + } + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ size - 1 ][ size - 2 ] = 1.0; + A[ size - 1 ][ size - 1 ] = -2.0; + for ( int i = 1; i < size - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + //Cyclic reduction + for ( int i = 0; i < std::log2( size + 1 ) - 1; ++ i ) + { + std::print( "Cyclic reduction i={}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + double alpha = A[ j ][ index1 ] / A[ index1 ][ index1 ]; + double gamma = A[ j ][ index2 ] / A[ index2 ][ index2 ]; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + for ( int k = 0; k < size; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ index1 ][ k ] + gamma * A[ index2 ][ k ] ); + std::print( "({},{})", j, k ); + } + std::println(); + F[ j ] -= ( alpha * F[ index1 ] + gamma * F[ index2 ] ); + } + } + //Back substitution + int index = ( size - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + for ( int i = std::log2( size + 1 ) - 2; i >= 0; -- i ) + { + std::print( "Back substitution i={}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + x[ index1 ] = F[ index1 ]; + x[ index2 ] = F[ index2 ]; + for ( int k = 0; k < size; ++ k ) + { + if ( k != index1 ) + { + x[ index1 ] -= A[ index1 ][ k ] * x[ k ]; + } + if ( k != index2 ) + { + x[ index2 ] -= A[ index2 ][ k ] * x[ k ]; + } + } + x[ index1 ] = x[ index1 ] / A[ index1 ][ index1 ]; + x[ index2 ] = x[ index2 ] / A[ index2 ][ index2 ]; + std::print( "x[{}] = {}, x[{}]={}\n", index1, x[ index1 ], index2, x[ index2 ] ); + } + } + + for ( int i = 0; i < size; ++ i ) + { + std::println( "{}", x[i] ); + } + + delete [] x; + delete [] F; + for ( int i = 0; i < size; ++ i ) + { + delete [] A[ i ]; + } + delete [] A; + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01c/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01c/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01c/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01c/main.cpp b/example/numerical/tdma/cpp/reference/serial/01c/main.cpp new file mode 100644 index 00000000..47cc2b44 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01c/main.cpp @@ -0,0 +1,101 @@ +import std; + +const int size = 15; + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + double * x = new double[ size ]; + for ( int i = 0; i < size; ++ i ) + { + x[ i ] = 0.0; + } + double * F = new double[ size ]; + double ** A = new double * [ size ]; + for ( int i = 0; i < size; ++ i ) + { + A[ i ] = new double[ size ]; + for ( int j = 0; j < size; ++ j ) + { + A[ i ][ j ] = 0.0; + } + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ size - 1 ][ size - 2 ] = 1.0; + A[ size - 1 ][ size - 1 ] = -2.0; + for ( int i = 1; i < size - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + //Cyclic reduction + for ( int i = 0; i < std::log2( size + 1 ) - 1; ++ i ) + { + std::print( "Cyclic reduction i={}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + double alpha = A[ j ][ index1 ] / A[ index1 ][ index1 ]; + double gamma = A[ j ][ index2 ] / A[ index2 ][ index2 ]; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + for ( int k = 0; k < size; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ index1 ][ k ] + gamma * A[ index2 ][ k ] ); + std::print( "({},{})", j, k ); + } + std::println(); + F[ j ] -= ( alpha * F[ index1 ] + gamma * F[ index2 ] ); + } + } + //Back substitution + int index = ( size - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + for ( int i = std::log2( size + 1 ) - 2; i >= 0; -- i ) + { + std::print( "Back substitution i={}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + x[ index1 ] = F[ index1 ]; + x[ index2 ] = F[ index2 ]; + for ( int k = 0; k < size; ++ k ) + { + if ( k != index1 ) + { + x[ index1 ] -= A[ index1 ][ k ] * x[ k ]; + } + if ( k != index2 ) + { + x[ index2 ] -= A[ index2 ][ k ] * x[ k ]; + } + } + x[ index1 ] = x[ index1 ] / A[ index1 ][ index1 ]; + x[ index2 ] = x[ index2 ] / A[ index2 ][ index2 ]; + std::print( "x[{}] = {}, x[{}]={}\n", index1, x[ index1 ], index2, x[ index2 ] ); + } + } + + for ( int i = 0; i < size; ++ i ) + { + std::println( "{}", x[i] ); + } + + delete [] x; + delete [] F; + for ( int i = 0; i < size; ++ i ) + { + delete [] A[ i ]; + } + delete [] A; + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01d/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01d/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01d/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01d/main.cpp b/example/numerical/tdma/cpp/reference/serial/01d/main.cpp new file mode 100644 index 00000000..2f578d00 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01d/main.cpp @@ -0,0 +1,93 @@ +import std; + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + const int size = 15; + std::vector x( size ); + for ( int i = 0; i < size; ++ i ) + { + x[ i ] = 0.0; + } + std::vector F( size ); + //double ** A = new double * [ size ]; + std::vector> A( size ); + for ( int i = 0; i < size; ++ i ) + { + A[ i ].resize( size ); + for ( int j = 0; j < size; ++ j ) + { + A[ i ][ j ] = 0.0; + } + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ size - 1 ][ size - 2 ] = 1.0; + A[ size - 1 ][ size - 1 ] = -2.0; + for ( int i = 1; i < size - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + //Cyclic reduction + for ( int i = 0; i < std::log2( size + 1 ) - 1; ++ i ) + { + std::print( "Cyclic reduction i={}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + double alpha = A[ j ][ index1 ] / A[ index1 ][ index1 ]; + double gamma = A[ j ][ index2 ] / A[ index2 ][ index2 ]; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + for ( int k = 0; k < size; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ index1 ][ k ] + gamma * A[ index2 ][ k ] ); + std::print( "({},{})", j, k ); + } + std::println(); + F[ j ] -= ( alpha * F[ index1 ] + gamma * F[ index2 ] ); + } + } + //Back substitution + int index = ( size - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + for ( int i = std::log2( size + 1 ) - 2; i >= 0; -- i ) + { + std::print( "Back substitution i={}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + x[ index1 ] = F[ index1 ]; + x[ index2 ] = F[ index2 ]; + for ( int k = 0; k < size; ++ k ) + { + if ( k != index1 ) + { + x[ index1 ] -= A[ index1 ][ k ] * x[ k ]; + } + if ( k != index2 ) + { + x[ index2 ] -= A[ index2 ][ k ] * x[ k ]; + } + } + x[ index1 ] = x[ index1 ] / A[ index1 ][ index1 ]; + x[ index2 ] = x[ index2 ] / A[ index2 ][ index2 ]; + std::print( "x[{}] = {}, x[{}]={}\n", index1, x[ index1 ], index2, x[ index2 ] ); + } + } + + for ( int i = 0; i < size; ++ i ) + { + std::println( "{}", x[i] ); + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01e/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01e/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01e/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01e/main.cpp b/example/numerical/tdma/cpp/reference/serial/01e/main.cpp new file mode 100644 index 00000000..d662e9ea --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01e/main.cpp @@ -0,0 +1,143 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + //const int size = 15; + const int size = 3; + std::vector x( size ); + for ( int i = 0; i < size; ++ i ) + { + x[ i ] = 0.0; + } + std::vector F( size ); + std::vector> A( size ); + for ( int i = 0; i < size; ++ i ) + { + A[ i ].resize( size ); + for ( int j = 0; j < size; ++ j ) + { + A[ i ][ j ] = 0.0; + } + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ size - 1 ][ size - 2 ] = 1.0; + A[ size - 1 ][ size - 1 ] = -2.0; + for ( int i = 1; i < size - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + Print( A, "matrix A" ); + + std::vector> AA = A; + std::vector FF = F; + + //Cyclic reduction + for ( int i = 0; i < std::log2( size + 1 ) - 1; ++ i ) + { + std::print( "Cyclic reduction i = {}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + double alpha = A[ j ][ index1 ] / A[ index1 ][ index1 ]; + double gamma = A[ j ][ index2 ] / A[ index2 ][ index2 ]; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + for ( int k = 0; k < size; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ index1 ][ k ] + gamma * A[ index2 ][ k ] ); + std::print( "({},{})", j, k ); + } + std::println(); + F[ j ] -= ( alpha * F[ index1 ] + gamma * F[ index2 ] ); + } + } + //Back substitution + int index = ( size - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + std::print( "F[{}] = {}, A[{}][{}]={}\n", index, F[ index ], index, index, A[ index ][ index ] ); + std::print( "x[{}] = {}\n", index, x[ index ] ); + for ( int i = std::log2( size + 1 ) - 2; i >= 0; -- i ) + { + std::print( "Back substitution i = {}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + x[ index1 ] = F[ index1 ]; + x[ index2 ] = F[ index2 ]; + for ( int k = 0; k < size; ++ k ) + { + if ( k != index1 ) + { + x[ index1 ] -= A[ index1 ][ k ] * x[ k ]; + } + if ( k != index2 ) + { + x[ index2 ] -= A[ index2 ][ k ] * x[ k ]; + } + } + x[ index1 ] = x[ index1 ] / A[ index1 ][ index1 ]; + x[ index2 ] = x[ index2 ] / A[ index2 ][ index2 ]; + std::print( "x[{}] = {}, x[{}] = {}\n", index1, x[ index1 ], index2, x[ index2 ] ); + } + } + + for ( int i = 0; i < size; ++ i ) + { + std::println( "{}", x[i] ); + } + + std::vector y( F.size() ); + MatrixMultiply( AA, x, y ); + Print( y, "y" ); + Print( FF, "FF" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01f/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01f/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01f/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01f/main.cpp b/example/numerical/tdma/cpp/reference/serial/01f/main.cpp new file mode 100644 index 00000000..2e4f8afa --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01f/main.cpp @@ -0,0 +1,154 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + //const int size = 15; + const int size = 3; + std::vector x( size ); + for ( int i = 0; i < size; ++ i ) + { + x[ i ] = 0.0; + } + std::vector F( size ); + std::vector> A( size ); + for ( int i = 0; i < size; ++ i ) + { + A[ i ].resize( size ); + for ( int j = 0; j < size; ++ j ) + { + A[ i ][ j ] = 0.0; + } + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ size - 1 ][ size - 2 ] = 1.0; + A[ size - 1 ][ size - 1 ] = -2.0; + for ( int i = 1; i < size - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + Print( A, "matrix A" ); + Print( F, "vector F" ); + + std::vector> AA = A; + std::vector FF = F; + + //Cyclic reduction + for ( int i = 0; i < std::log2( size + 1 ) - 1; ++ i ) + { + std::print( "Cyclic reduction i = {}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + double alpha = A[ j ][ index1 ] / A[ index1 ][ index1 ]; + double gamma = A[ j ][ index2 ] / A[ index2 ][ index2 ]; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + std::print( "A[{}][{}]={}\n", j, index1, A[ j ][ index1 ] ); + std::print( "A[{}][{}]={}\n", j, index2, A[ j ][ index2 ] ); + std::print( "A[{}][{}]={}\n", index1, index1, A[ index1 ][ index1 ] ); + std::print( "A[{}][{}]={}\n", index2, index2, A[ index2 ][ index2 ] ); + std::print( "alpha = {}, gamma = {}\n", alpha, gamma ); + for ( int k = 0; k < size; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ index1 ][ k ] + gamma * A[ index2 ][ k ] ); + std::print( "j,k=({},{}) ", j, k ); + std::print( "index1,k=({},{}) ", index1, k ); + std::print( "index2,k=({},{}) \n", index2, k ); + } + std::println(); + F[ j ] -= ( alpha * F[ index1 ] + gamma * F[ index2 ] ); + } + } + + Print( A, "matrix A after cyclic reduction" ); + Print( F, "vector F after cyclic reduction" ); + //Back substitution + int index = ( size - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + std::print( "F[{}] = {}, A[{}][{}]={}\n", index, F[ index ], index, index, A[ index ][ index ] ); + std::print( "x[{}] = {}\n", index, x[ index ] ); + for ( int i = std::log2( size + 1 ) - 2; i >= 0; -- i ) + { + std::print( "Back substitution i = {}\n", i ); + for ( int j = std::pow( 2, i + 1 ) - 1; j < size; j = j + std::pow( 2, i + 1 ) ) + { + int offset = std::pow( 2, i ); + int index1 = j - offset; + int index2 = j + offset; + std::print( "index1,j,index2 = ({},{},{})\n", index1, j, index2 ); + x[ index1 ] = F[ index1 ]; + x[ index2 ] = F[ index2 ]; + for ( int k = 0; k < size; ++ k ) + { + if ( k != index1 ) + { + x[ index1 ] -= A[ index1 ][ k ] * x[ k ]; + } + if ( k != index2 ) + { + x[ index2 ] -= A[ index2 ][ k ] * x[ k ]; + } + } + x[ index1 ] = x[ index1 ] / A[ index1 ][ index1 ]; + x[ index2 ] = x[ index2 ] / A[ index2 ][ index2 ]; + std::print( "x[{}] = {}, x[{}] = {}\n", index1, x[ index1 ], index2, x[ index2 ] ); + } + } + + for ( int i = 0; i < size; ++ i ) + { + std::println( "{}", x[i] ); + } + + std::vector y( F.size() ); + MatrixMultiply( AA, x, y ); + Print( y, "y" ); + Print( FF, "FF" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01g/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01g/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01g/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01g/main.cpp b/example/numerical/tdma/cpp/reference/serial/01g/main.cpp new file mode 100644 index 00000000..d5d73543 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01g/main.cpp @@ -0,0 +1,153 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + const int size = 3; + std::vector x( size ); + for ( int i = 0; i < size; ++ i ) + { + x[ i ] = 0.0; + } + std::vector F( size ); + std::vector> A( size ); + for ( int i = 0; i < size; ++ i ) + { + A[ i ].resize( size ); + for ( int j = 0; j < size; ++ j ) + { + A[ i ][ j ] = 0.0; + } + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ size - 1 ][ size - 2 ] = 1.0; + A[ size - 1 ][ size - 1 ] = -2.0; + for ( int i = 1; i < size - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + Print( A, "matrix A" ); + Print( F, "vector F" ); + + std::vector> AA = A; + std::vector FF = F; + + //Cyclic reduction + for ( int level = 0; level < std::log2( size + 1 ) - 1; ++ level ) + { + std::print( "Cyclic reduction level = {}\n", level ); + for ( int j = std::pow( 2, level + 1 ) - 1; j < size; j = j + std::pow( 2, level + 1 ) ) + { + int offset = std::pow( 2, level ); + int in = j - offset; + int ip = j + offset; + double alpha = A[ j ][ in ] / A[ in ][ in ]; + double gamma = A[ j ][ ip ] / A[ ip ][ ip ]; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + std::print( "A[{}][{}]={}\n", j, in, A[ j ][ in ] ); + std::print( "A[{}][{}]={}\n", j, ip, A[ j ][ ip ] ); + std::print( "A[{}][{}]={}\n", in, in, A[ in ][ in ] ); + std::print( "A[{}][{}]={}\n", ip, ip, A[ ip ][ ip ] ); + std::print( "alpha = {}, gamma = {}\n", alpha, gamma ); + for ( int k = 0; k < size; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ in ][ k ] + gamma * A[ ip ][ k ] ); + std::print( "j,k=({},{}) ", j, k ); + std::print( "in,k=({},{}) ", in, k ); + std::print( "ip,k=({},{}) \n", ip, k ); + } + std::println(); + F[ j ] -= ( alpha * F[ in ] + gamma * F[ ip ] ); + } + } + + Print( A, "matrix A after cyclic reduction" ); + Print( F, "vector F after cyclic reduction" ); + //Back substitution + int index = ( size - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + std::print( "F[{}] = {}, A[{}][{}]={}\n", index, F[ index ], index, index, A[ index ][ index ] ); + std::print( "x[{}] = {}\n", index, x[ index ] ); + for ( int level = std::log2( size + 1 ) - 2; level >= 0; -- level ) + { + std::print( "Back substitution level = {}\n", level ); + for ( int j = std::pow( 2, level + 1 ) - 1; j < size; j = j + std::pow( 2, level + 1 ) ) + { + int offset = std::pow( 2, level ); + int in = j - offset; + int ip = j + offset; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + x[ in ] = F[ in ]; + x[ ip ] = F[ ip ]; + for ( int k = 0; k < size; ++ k ) + { + if ( k != in ) + { + x[ in ] -= A[ in ][ k ] * x[ k ]; + } + if ( k != ip ) + { + x[ ip ] -= A[ ip ][ k ] * x[ k ]; + } + } + x[ in ] = x[ in ] / A[ in ][ in ]; + x[ ip ] = x[ ip ] / A[ ip ][ ip ]; + std::print( "x[{}] = {}, x[{}] = {}\n", in, x[ in ], ip, x[ ip ] ); + } + } + + for ( int i = 0; i < size; ++ i ) + { + std::println( "{}", x[i] ); + } + + std::vector y( F.size() ); + MatrixMultiply( AA, x, y ); + Print( y, "y" ); + Print( FF, "FF" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01h/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01h/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01h/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01h/main.cpp b/example/numerical/tdma/cpp/reference/serial/01h/main.cpp new file mode 100644 index 00000000..93029676 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01h/main.cpp @@ -0,0 +1,158 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + const int size = 3; + //const int size = 15; + std::vector x( size ); + for ( int i = 0; i < size; ++ i ) + { + x[ i ] = 0.0; + } + std::vector F( size ); + std::vector> A( size ); + for ( int i = 0; i < size; ++ i ) + { + A[ i ].resize( size ); + for ( int j = 0; j < size; ++ j ) + { + A[ i ][ j ] = 0.0; + } + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ size - 1 ][ size - 2 ] = 1.0; + A[ size - 1 ][ size - 1 ] = -2.0; + for ( int i = 1; i < size - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + Print( A, "matrix A" ); + Print( F, "vector F" ); + + std::vector> AA = A; + std::vector FF = F; + + //Cyclic reduction + for ( int level = 0; level < std::log2( size + 1 ) - 1; ++ level ) + { + std::print( "Cyclic reduction level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < size; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + double alpha = A[ j ][ in ] / A[ in ][ in ]; + double gamma = A[ j ][ ip ] / A[ ip ][ ip ]; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + std::print( "A[{}][{}]={}\n", j, in, A[ j ][ in ] ); + std::print( "A[{}][{}]={}\n", j, ip, A[ j ][ ip ] ); + std::print( "A[{}][{}]={}\n", in, in, A[ in ][ in ] ); + std::print( "A[{}][{}]={}\n", ip, ip, A[ ip ][ ip ] ); + std::print( "alpha = {}, gamma = {}\n", alpha, gamma ); + for ( int k = 0; k < size; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ in ][ k ] + gamma * A[ ip ][ k ] ); + std::print( "j,k=({},{}) ", j, k ); + std::print( "in,k=({},{}) ", in, k ); + std::print( "ip,k=({},{}) \n", ip, k ); + } + std::println(); + F[ j ] -= ( alpha * F[ in ] + gamma * F[ ip ] ); + } + } + + Print( A, "matrix A after cyclic reduction" ); + Print( F, "vector F after cyclic reduction" ); + //Back substitution + int index = ( size - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + std::print( "F[{}] = {}, A[{}][{}]={}\n", index, F[ index ], index, index, A[ index ][ index ] ); + std::print( "x[{}] = {}\n", index, x[ index ] ); + for ( int level = std::log2( size + 1 ) - 2; level >= 0; -- level ) + { + std::print( "Back substitution level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < size; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + x[ in ] = F[ in ]; + x[ ip ] = F[ ip ]; + for ( int k = 0; k < size; ++ k ) + { + if ( k != in ) + { + x[ in ] -= A[ in ][ k ] * x[ k ]; + } + if ( k != ip ) + { + x[ ip ] -= A[ ip ][ k ] * x[ k ]; + } + } + x[ in ] = x[ in ] / A[ in ][ in ]; + x[ ip ] = x[ ip ] / A[ ip ][ ip ]; + std::print( "x[{}] = {}, x[{}] = {}\n", in, x[ in ], ip, x[ ip ] ); + } + } + + for ( int i = 0; i < size; ++ i ) + { + std::println( "{}", x[i] ); + } + + std::vector y( F.size() ); + MatrixMultiply( AA, x, y ); + Print( y, "y" ); + Print( FF, "FF" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01i/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01i/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01i/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01i/main.cpp b/example/numerical/tdma/cpp/reference/serial/01i/main.cpp new file mode 100644 index 00000000..aa7d17a6 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01i/main.cpp @@ -0,0 +1,193 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + //const int N = 3; + const int N = 7; + //const int N = 15; + std::vector a( N ); + std::vector b( N ); + std::vector c( N ); + std::vector y( N ); + std::vector x( N ); + std::vector xx( N ); + for ( int i = 0; i < N; ++ i ) + { + xx[ i ] = 0.0; + } + std::vector F( N ); + std::vector> A( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + for ( int j = 0; j < N; ++ j ) + { + A[ i ][ j ] = 0.0; + } + a[ i ] = 1; + b[ i ] = -2; + c[ i ] = 1; + y[ i ] = i; + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ N - 1 ][ N - 2 ] = 1.0; + A[ N - 1 ][ N - 1 ] = -2.0; + + for ( int i = 1; i < N - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + Print( A, "matrix A" ); + Print( F, "vector F" ); + + std::vector> AA = A; + std::vector FF = F; + + //Cyclic reduction + for ( int level = 0; level < std::log2( N + 1 ) - 1; ++ level ) + { + std::print( "Cyclic reduction level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + double alpha = A[ j ][ in ] / A[ in ][ in ]; + double gamma = A[ j ][ ip ] / A[ ip ][ ip ]; + + double alpha1 = a[ j ] / b[ in ]; + double gamma1 = c[ j ] / b[ ip ]; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + std::print( "A[{}][{}]={}\n", j, in, A[ j ][ in ] ); + std::print( "A[{}][{}]={}\n", j, ip, A[ j ][ ip ] ); + std::print( "A[{}][{}]={}\n", in, in, A[ in ][ in ] ); + std::print( "A[{}][{}]={}\n", ip, ip, A[ ip ][ ip ] ); + std::print( "alpha = {}, gamma = {}\n", alpha, gamma ); + for ( int k = 0; k < N; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ in ][ k ] + gamma * A[ ip ][ k ] ); + std::print( "j,k=({},{}) ", j, k ); + std::print( "in,k=({},{}) ", in, k ); + std::print( "ip,k=({},{}) \n", ip, k ); + } + std::println(); + b[ j ] -= ( alpha1 * c[ in ] + gamma1 * a[ ip ] ); + a[ j ] = - alpha1 * a[ in ]; + c[ j ] = - gamma1 * c[ ip ]; + y[ j ] -= ( alpha1 * y[ in ] + gamma1 * y[ ip ] ); + F[ j ] -= ( alpha * F[ in ] + gamma * F[ ip ] ); + } + } + + Print( A, "matrix A after cyclic reduction" ); + Print( F, "vector F after cyclic reduction" ); + //Back substitution + int index = ( N - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + xx[ index ] = y[ index ] / b[ index ]; + std::print( "F[{}] = {}, A[{}][{}]={}\n", index, F[ index ], index, index, A[ index ][ index ] ); + std::print( "x[{}] = {}\n", index, x[ index ] ); + for ( int level = std::log2( N + 1 ) - 2; level >= 0; -- level ) + { + std::print( "Back substitution level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + x[ in ] = F[ in ]; + x[ ip ] = F[ ip ]; + for ( int k = 0; k < N; ++ k ) + { + if ( k != in ) + { + x[ in ] -= A[ in ][ k ] * x[ k ]; + } + if ( k != ip ) + { + x[ ip ] -= A[ ip ][ k ] * x[ k ]; + } + } + x[ in ] = x[ in ] / A[ in ][ in ]; + x[ ip ] = x[ ip ] / A[ ip ][ ip ]; + std::print( "x[{}] = {}, x[{}] = {}\n", in, x[ in ], ip, x[ ip ] ); + + if ( in - joffset < 0 ) + { + xx[ in ] = ( y[ in ] - c[ in ] * xx[ in + joffset ] ) / b[ in ]; + } + else + { + xx[ in ] = ( y[ in ] - a[ in ] * xx[ in - joffset ] - c[ in ] * xx[ in + joffset ] ) / b[ in ]; + } + + if ( ip + joffset >= N ) + { + xx[ ip ] = ( y[ ip ] - a[ ip ] * xx[ ip - joffset ] ) / b[ ip ]; + } + else + { + xx[ ip ] = ( y[ ip ] - a[ ip ] * xx[ ip - joffset ] - c[ ip ] * xx[ ip + joffset ] ) / b[ ip ]; + } + } + } + + Print( x, "x" ); + Print( xx, "xx" ); + + std::vector ff( F.size() ); + MatrixMultiply( AA, x, ff ); + Print( ff, "ff" ); + Print( FF, "FF" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01i0/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01i0/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01i0/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01i0/main.cpp b/example/numerical/tdma/cpp/reference/serial/01i0/main.cpp new file mode 100644 index 00000000..acee5910 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01i0/main.cpp @@ -0,0 +1,209 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print000( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + std::cout << name << " = \n"; + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::cout << std::format( "{:5.2f} ", a[ i ][ j ] ); + } + std::cout << "\n"; + } + std::cout << "\n"; +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + //const int N = 3; + const int N = 7; + //const int N = 15; + std::vector a( N ); + std::vector b( N ); + std::vector c( N ); + std::vector y( N ); + std::vector x( N ); + std::vector xx( N ); + for ( int i = 0; i < N; ++ i ) + { + xx[ i ] = 0.0; + } + std::vector F( N ); + std::vector> A( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + for ( int j = 0; j < N; ++ j ) + { + A[ i ][ j ] = 0.0; + } + a[ i ] = 1; + b[ i ] = -2; + c[ i ] = 1; + y[ i ] = i; + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ N - 1 ][ N - 2 ] = 1.0; + A[ N - 1 ][ N - 1 ] = -2.0; + + for ( int i = 1; i < N - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + Print( A, "matrix A 0" ); + Print( F, "vector F" ); + + std::vector> AA = A; + std::vector FF = F; + + //Cyclic reduction + for ( int level = 0; level < std::log2( N + 1 ) - 1; ++ level ) + { + std::print( "Cyclic reduction level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + double alpha = A[ j ][ in ] / A[ in ][ in ]; + double gamma = A[ j ][ ip ] / A[ ip ][ ip ]; + + double alpha1 = a[ j ] / b[ in ]; + double gamma1 = c[ j ] / b[ ip ]; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + std::print( "A[{}][{}]={}\n", j, in, A[ j ][ in ] ); + std::print( "A[{}][{}]={}\n", j, ip, A[ j ][ ip ] ); + std::print( "A[{}][{}]={}\n", in, in, A[ in ][ in ] ); + std::print( "A[{}][{}]={}\n", ip, ip, A[ ip ][ ip ] ); + std::print( "alpha = {}, gamma = {}\n", alpha, gamma ); + for ( int k = 0; k < N; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ in ][ k ] + gamma * A[ ip ][ k ] ); + std::print( "j,k=({},{}) ", j, k ); + std::print( "in,k=({},{}) ", in, k ); + std::print( "ip,k=({},{}) \n", ip, k ); + } + std::println(); + b[ j ] -= ( alpha1 * c[ in ] + gamma1 * a[ ip ] ); + a[ j ] = - alpha1 * a[ in ]; + c[ j ] = - gamma1 * c[ ip ]; + y[ j ] -= ( alpha1 * y[ in ] + gamma1 * y[ ip ] ); + F[ j ] -= ( alpha * F[ in ] + gamma * F[ ip ] ); + } + } + + Print( A, "matrix A after cyclic reduction" ); + Print( F, "vector F after cyclic reduction" ); + //Back substitution + int index = ( N - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + xx[ index ] = y[ index ] / b[ index ]; + std::print( "F[{}] = {}, A[{}][{}]={}\n", index, F[ index ], index, index, A[ index ][ index ] ); + std::print( "x[{}] = {}\n", index, x[ index ] ); + for ( int level = std::log2( N + 1 ) - 2; level >= 0; -- level ) + { + std::print( "Back substitution level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + x[ in ] = F[ in ]; + x[ ip ] = F[ ip ]; + for ( int k = 0; k < N; ++ k ) + { + if ( k != in ) + { + x[ in ] -= A[ in ][ k ] * x[ k ]; + } + if ( k != ip ) + { + x[ ip ] -= A[ ip ][ k ] * x[ k ]; + } + } + x[ in ] = x[ in ] / A[ in ][ in ]; + x[ ip ] = x[ ip ] / A[ ip ][ ip ]; + std::print( "x[{}] = {}, x[{}] = {}\n", in, x[ in ], ip, x[ ip ] ); + + if ( in - joffset < 0 ) + { + xx[ in ] = ( y[ in ] - c[ in ] * xx[ in + joffset ] ) / b[ in ]; + } + else + { + xx[ in ] = ( y[ in ] - a[ in ] * xx[ in - joffset ] - c[ in ] * xx[ in + joffset ] ) / b[ in ]; + } + + if ( ip + joffset >= N ) + { + xx[ ip ] = ( y[ ip ] - a[ ip ] * xx[ ip - joffset ] ) / b[ ip ]; + } + else + { + xx[ ip ] = ( y[ ip ] - a[ ip ] * xx[ ip - joffset ] - c[ ip ] * xx[ ip + joffset ] ) / b[ ip ]; + } + } + } + + Print( x, "x" ); + Print( xx, "xx" ); + + std::vector ff( F.size() ); + MatrixMultiply( AA, x, ff ); + Print( ff, "ff" ); + Print( FF, "FF" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/01j/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/01j/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01j/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/01j/main.cpp b/example/numerical/tdma/cpp/reference/serial/01j/main.cpp new file mode 100644 index 00000000..67aec82b --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/01j/main.cpp @@ -0,0 +1,314 @@ +import std; + +template +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print000( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + std::cout << name << " = \n"; + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::cout << std::format( "{:5.2f} ", a[ i ][ j ] ); + } + std::cout << "\n"; + } + std::cout << "\n"; +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + +void SetProcessMatrixValue( std::vector>> &AList,int N, int nProc ) +{ + AList.resize( nProc ); + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + int nRow = 3; + AList[ iProc ].resize( nRow ); + for ( int i = 0; i < nRow; ++ i ) + { + AList[ iProc ][ i ].resize( N, 0 ); + } + + } + for ( int iProc = 0; iProc < nProc; ++ iProc ) + { + std::vector> & A = AList[ iProc ]; + //int loc = 2 * iProc + 1; //1,3,5,7,9,11,13 + int loc = 2 * iProc; //0,2,4,6,8,10,12 + std::vector global_locs( 3 ); + for ( int i = 0; i < 3; ++ i ) + { + int iloc = loc + i; + global_locs[ i ] = iloc; + if ( ( iloc - 1 ) >= 0 ) + { + A[ i ][ iloc - 1 ] = 1.0; + } + A[ i ][ iloc ] = -2.0; + if ( ( iloc + 1 ) < N ) + { + A[ i ][ iloc + 1 ] = 1.0; + } + } + std::print("iProc={}\n", iProc ); + Print( global_locs, "global_locs" ); + Print( A, "matrix A" ); + } +} + + +int main( int argc, char ** argv ) +{ + //p = 0, N = 0, nprocs = -1 + //p = 1, N = 1, nprocs = 0 + //p = 2, N = 3, nprocs = 1 + //p = 3, N = 7, nprocs = 3 + //p = 4, N = 15, nprocs = 7 + //p = 5, N = 31, nprocs = 15 + //p = 6, N = 63, nprocs = 31 + //p = 7, N = 127, nprocs = 63 + //p = 8, N = 255, nprocs = 127 + //p = 9, N = 511, nprocs = 255 + //p = 10, N = 1023, nprocs = 511 + //Memory allocation and generation of matrix + + int nprocs = 3; + int N = std::pow( 2, std::log2( nprocs + 1 ) + 1 ) - 1; + + std::vector a( N ); + std::vector b( N ); + std::vector c( N ); + std::vector y( N ); + std::vector x( N ); + std::vector xx( N ); + for ( int i = 0; i < N; ++ i ) + { + xx[ i ] = 0.0; + } + std::vector F( N ); + std::vector> A( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + for ( int j = 0; j < N; ++ j ) + { + A[ i ][ j ] = 0.0; + } + a[ i ] = 1; + b[ i ] = -2; + c[ i ] = 1; + y[ i ] = i; + F[ i ] = i; + } + A[ 0 ][ 0 ] = -2.0; + A[ 0 ][ 1 ] = 1.0; + A[ N - 1 ][ N - 2 ] = 1.0; + A[ N - 1 ][ N - 1 ] = -2.0; + + for ( int i = 1; i < N - 1; ++ i ) + { + A[ i ][ i ] = -2.0; + A[ i ][ i - 1 ] = 1.0; + A[ i ][ i + 1 ] = 1.0; + } + + Print( A, "matrix A 0" ); + Print( F, "vector F" ); + + std::vector>> AProcs; + SetProcessMatrixValue( AProcs, N, nprocs ); + + std::vector> AA = A; + std::vector FF = F; + + //Cyclic reduction + for ( int level = 0; level < std::log2( N + 1 ) - 1; ++ level ) + { + std::print( "Cyclic reduction level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + std::print( "j = " ); + for ( int j = jstart; j < N; j = j + jstep ) + { + std::print( "{} ", j ); + } + std::println(); + std::print( "in = " ); + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + std::print( "{} ", in ); + } + std::println(); + std::print( "ip = " ); + for ( int j = jstart; j < N; j = j + jstep ) + { + int ip = j + joffset; + std::print( "{} ", ip ); + } + std::println(); + + //j=1,3,5 + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + double alpha = A[ j ][ in ] / A[ in ][ in ]; + double gamma = A[ j ][ ip ] / A[ ip ][ ip ]; + + double alpha1 = a[ j ] / b[ in ]; + double gamma1 = c[ j ] / b[ ip ]; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + std::print( "alpha = {}, gamma = {}\n", alpha, gamma ); + for ( int k = 0; k < N; ++ k ) + { + A[ j ][ k ] -= ( alpha * A[ in ][ k ] + gamma * A[ ip ][ k ] ); + } + std::println(); + b[ j ] -= ( alpha1 * c[ in ] + gamma1 * a[ ip ] ); + a[ j ] = - alpha1 * a[ in ]; + c[ j ] = - gamma1 * c[ ip ]; + y[ j ] -= ( alpha1 * y[ in ] + gamma1 * y[ ip ] ); + F[ j ] -= ( alpha * F[ in ] + gamma * F[ ip ] ); + } + + std::vector jlist; + jlist.push_back(1); + jlist.push_back(3); + jlist.push_back(5); + std::vector jlocals; + jlocals.push_back(1); + jlocals.push_back(1); + jlocals.push_back(1); + + for ( int iProc = 0; iProc < nprocs; ++ iProc ) + { + std::vector> &AProc = AProcs[iProc]; + Print( AProc, std::format( "iProc = {} Matrix AProc 000 ", iProc ) ); + } + + for ( int iProc = 0; iProc < nprocs; ++ iProc ) + { + std::vector> &AProc = AProcs[iProc]; + int j = jlist[iProc]; + int jl = jlocals[iProc]; + + int inl = jl - joffset; + int ipl = jl + joffset; + int in = j - joffset; + int ip = j + joffset; + double alpha = AProc[ jl ][ in ] / AProc[ inl ][ in ]; + double gamma = AProc[ jl ][ ip ] / AProc[ ipl ][ ip ]; + for ( int k = 0; k < N; ++ k ) + { + AProc[ jl ][ k ] -= ( alpha * AProc[ inl ][ k ] + gamma * AProc[ ipl ][ k ] ); + } + Print( AProc, std::format( "level = {} iProc = {} Matrix AProc ", level, iProc ) ); + } + int kkk = 1; + } + + Print( A, "matrix A after cyclic reduction" ); + Print( F, "vector F after cyclic reduction" ); + //Back substitution + int index = ( N - 1 ) / 2; + x[ index ] = F[ index ] / A[ index ][ index ]; + xx[ index ] = y[ index ] / b[ index ]; + std::print( "F[{}] = {}, A[{}][{}]={}\n", index, F[ index ], index, index, A[ index ][ index ] ); + std::print( "x[{}] = {}\n", index, x[ index ] ); + for ( int level = std::log2( N + 1 ) - 2; level >= 0; -- level ) + { + std::print( "Back substitution level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + x[ in ] = F[ in ]; + x[ ip ] = F[ ip ]; + for ( int k = 0; k < N; ++ k ) + { + if ( k != in ) + { + x[ in ] -= A[ in ][ k ] * x[ k ]; + } + if ( k != ip ) + { + x[ ip ] -= A[ ip ][ k ] * x[ k ]; + } + } + x[ in ] = x[ in ] / A[ in ][ in ]; + x[ ip ] = x[ ip ] / A[ ip ][ ip ]; + std::print( "x[{}] = {}, x[{}] = {}\n", in, x[ in ], ip, x[ ip ] ); + + if ( in - joffset < 0 ) + { + xx[ in ] = ( y[ in ] - c[ in ] * xx[ in + joffset ] ) / b[ in ]; + } + else + { + xx[ in ] = ( y[ in ] - a[ in ] * xx[ in - joffset ] - c[ in ] * xx[ in + joffset ] ) / b[ in ]; + } + + if ( ip + joffset >= N ) + { + xx[ ip ] = ( y[ ip ] - a[ ip ] * xx[ ip - joffset ] ) / b[ ip ]; + } + else + { + xx[ ip ] = ( y[ ip ] - a[ ip ] * xx[ ip - joffset ] - c[ ip ] * xx[ ip + joffset ] ) / b[ ip ]; + } + } + } + + Print( x, "x" ); + Print( xx, "xx" ); + + std::vector ff( F.size() ); + MatrixMultiply( AA, x, ff ); + Print( ff, "ff" ); + Print( FF, "FF" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/02/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/02/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/02/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/02/main.cpp b/example/numerical/tdma/cpp/reference/serial/02/main.cpp new file mode 100644 index 00000000..2068ea50 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/02/main.cpp @@ -0,0 +1,122 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + //const int N = 3; + const int N = 7; + //const int N = 15; + std::vector a( N ); + std::vector b( N ); + std::vector c( N ); + std::vector y( N ); + std::vector x( N ); + for ( int i = 0; i < N; ++ i ) + { + a[ i ] = 1; + b[ i ] = -2; + c[ i ] = 1; + y[ i ] = i; + } + + //Cyclic reduction + for ( int level = 0; level < std::log2( N + 1 ) - 1; ++ level ) + { + std::print( "Cyclic reduction level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + + double alpha1 = a[ j ] / b[ in ]; + double gamma1 = c[ j ] / b[ ip ]; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + std::println(); + b[ j ] -= ( alpha1 * c[ in ] + gamma1 * a[ ip ] ); + a[ j ] = - alpha1 * a[ in ]; + c[ j ] = - gamma1 * c[ ip ]; + y[ j ] -= ( alpha1 * y[ in ] + gamma1 * y[ ip ] ); + } + } + + //Back substitution + int index = ( N - 1 ) / 2; + x[ index ] = y[ index ] / b[ index ]; + std::print( "x[{}] = {}\n", index, x[ index ] ); + for ( int level = std::log2( N + 1 ) - 2; level >= 0; -- level ) + { + std::print( "Back substitution level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + + if ( in - joffset < 0 ) + { + x[ in ] = ( y[ in ] - c[ in ] * x[ in + joffset ] ) / b[ in ]; + } + else + { + x[ in ] = ( y[ in ] - a[ in ] * x[ in - joffset ] - c[ in ] * x[ in + joffset ] ) / b[ in ]; + } + + if ( ip + joffset >= N ) + { + x[ ip ] = ( y[ ip ] - a[ ip ] * x[ ip - joffset ] ) / b[ ip ]; + } + else + { + x[ ip ] = ( y[ ip ] - a[ ip ] * x[ ip - joffset ] - c[ ip ] * x[ ip + joffset ] ) / b[ ip ]; + } + } + } + + Print( x, "x" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/reference/serial/02a/CMakeLists.txt b/example/numerical/tdma/cpp/reference/serial/02a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/02a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/reference/serial/02a/main.cpp b/example/numerical/tdma/cpp/reference/serial/02a/main.cpp new file mode 100644 index 00000000..867c0227 --- /dev/null +++ b/example/numerical/tdma/cpp/reference/serial/02a/main.cpp @@ -0,0 +1,139 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print000( std::vector> & a, const std::string & name = "matrix" ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + for ( int j = 0; j < N; ++ j ) + { + std::print( "{:10f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + std::cout << name << " = \n"; + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::cout << std::format( "{:5.2f} ", a[ i ][ j ] ); + } + std::cout << "\n"; + } + std::cout << "\n"; +} + + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + + +int main( int argc, char ** argv ) +{ + //Memory allocation and generation of matrix + //const int N = 3; + const int N = 7; + //const int N = 15; + std::vector a( N ); + std::vector b( N ); + std::vector c( N ); + std::vector y( N ); + std::vector x( N ); + for ( int i = 0; i < N; ++ i ) + { + a[ i ] = 1; + b[ i ] = -2; + c[ i ] = 1; + y[ i ] = i; + } + + //Cyclic reduction + for ( int level = 0; level < std::log2( N + 1 ) - 1; ++ level ) + { + std::print( "Cyclic reduction level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + + double alpha1 = a[ j ] / b[ in ]; + double gamma1 = c[ j ] / b[ ip ]; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + std::println(); + b[ j ] -= ( alpha1 * c[ in ] + gamma1 * a[ ip ] ); + a[ j ] = - alpha1 * a[ in ]; + c[ j ] = - gamma1 * c[ ip ]; + y[ j ] -= ( alpha1 * y[ in ] + gamma1 * y[ ip ] ); + } + } + + //Back substitution + int index = ( N - 1 ) / 2; + x[ index ] = y[ index ] / b[ index ]; + std::print( "x[{}] = {}\n", index, x[ index ] ); + for ( int level = std::log2( N + 1 ) - 2; level >= 0; -- level ) + { + std::print( "Back substitution level = {}\n", level ); + int joffset = std::pow( 2, level ); + int jstep = std::pow( 2, level + 1 ); + int jstart = jstep - 1; + for ( int j = jstart; j < N; j = j + jstep ) + { + int in = j - joffset; + int ip = j + joffset; + std::print( "in,j,ip = ({},{},{})\n", in, j, ip ); + + if ( in - joffset < 0 ) + { + x[ in ] = ( y[ in ] - c[ in ] * x[ in + joffset ] ) / b[ in ]; + } + else + { + x[ in ] = ( y[ in ] - a[ in ] * x[ in - joffset ] - c[ in ] * x[ in + joffset ] ) / b[ in ]; + } + + if ( ip + joffset >= N ) + { + x[ ip ] = ( y[ ip ] - a[ ip ] * x[ ip - joffset ] ) / b[ ip ]; + } + else + { + x[ ip ] = ( y[ ip ] - a[ ip ] * x[ ip - joffset ] - c[ ip ] * x[ ip + joffset ] ) / b[ ip ]; + } + } + } + + Print( x, "x" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/serial/01/CMakeLists.txt b/example/numerical/tdma/cpp/serial/01/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/01/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/serial/01/main.cpp b/example/numerical/tdma/cpp/serial/01/main.cpp new file mode 100644 index 00000000..eab9fd13 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/01/main.cpp @@ -0,0 +1,47 @@ +import std; + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + const std::vector & d, + std::vector & x ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double r = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + d_star[ i ] = r * ( d[ i ] - a[ i ] * d_star[ i - 1 ] ); + c_star[ i ] = r * c[ i ]; + } + + x[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + x[ i ] = d_star[ i ] - c_star[ i ] * x[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + std::vector a{ 0, -1, -1, -1, -1 }; // ϶ԽÇÏß + std::vector b{ 2, 2, 2, 2, 2 }; // Ö÷¶Ô½ÇÏß + std::vector c{ -1, -1, -1, -1, 0 }; // É϶ԽÇÏß + std::vector d{ 1.0, 1.0, 1.0, 1.0, 1.0 }; // Óұߵij£ÊýÏòÁ¿ + std::vector x( d.size() ); // ½á¹ûÏòÁ¿ + + thomas_algorithm( a, b, c, d, x ); + for ( auto v : x ) + { + std::print( "{} ", v ); + } + + return 0; +} diff --git a/example/numerical/tdma/cpp/serial/01a/CMakeLists.txt b/example/numerical/tdma/cpp/serial/01a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/01a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/serial/01a/main.cpp b/example/numerical/tdma/cpp/serial/01a/main.cpp new file mode 100644 index 00000000..bbeaa6e4 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/01a/main.cpp @@ -0,0 +1,53 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + std::vector & d ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double r = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + d_star[ i ] = r * ( d[ i ] - a[ i ] * d_star[ i - 1 ] ); + c_star[ i ] = r * c[ i ]; + } + + d[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + d[ i ] = d_star[ i ] - c_star[ i ] * d[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + std::vector a{ 0, -1, -1, -1, -1 }; // ϶ԽÇÏß + std::vector b{ 2, 2, 2, 2, 2 }; // Ö÷¶Ô½ÇÏß + std::vector c{ -1, -1, -1, -1, 0 }; // É϶ԽÇÏß + std::vector d{ 1.0, 1.0, 1.0, 1.0, 1.0 }; // Óұߵij£ÊýÏòÁ¿ + + Print( d, "d" ); + thomas_algorithm( a, b, c, d ); + Print( d, "results" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/serial/02/CMakeLists.txt b/example/numerical/tdma/cpp/serial/02/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/02/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/serial/02/main.cpp b/example/numerical/tdma/cpp/serial/02/main.cpp new file mode 100644 index 00000000..abd7cab5 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/02/main.cpp @@ -0,0 +1,135 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void ThomasAlgorithm( int N, double * b, double * a, double * c, double * x, double * q ) +{ + double *l,*u,*d,*y; + l = new double[ N ]; + u = new double[ N ]; + d = new double[ N ]; + y = new double[ N ]; + /* LU Decomposition */ + d[ 0 ] = a[ 0 ]; + u[ 0 ] = c[ 0 ]; + for ( int i = 1; i < N - 1; i++ ) + { + l[ i ] = b[ i ] / d[ i - 1 ]; + d[ i ] = a[ i ] - l[ i ] * u[ i - 1 ]; + u[ i ] = c[ i ]; + } + l[ N - 1 ] = b[ N - 1 ] / d[ N - 2 ]; + d[ N - 1 ] = a[ N - 1 ] - l[ N - 1 ] * u[ N - 2 ]; + /* Forward Substitution [L][y] = [q] */ + y[ 0 ] = q[ 0 ]; + for ( int i = 1; i < N; i++ ) + { + y[ i ] = q[ i ] - l[ i ] * y[ i - 1 ]; + } + /* Backward Substitution [U][x] = [y] */ + x[ N - 1 ] = y[ N - 1 ] / d[ N - 1 ]; + for ( int i = N - 2; i >= 0; i-- ) + { + x[ i ] = ( y[ i ] - u[ i ] * x[ i + 1 ] ) / d[ i ]; + } + delete[] l; + delete[] u; + delete[] d; + delete[] y; + return; +} + +void ThomasAlgorithmBAK( int N, double * b, double * a, double * c, double * x, double * q ) +{ + double *l,*u,*d,*y; + l = new double[ N ]; + u = new double[ N ]; + d = new double[ N ]; + y = new double[ N ]; + /* LU Decomposition */ + d[ 0 ] = a[ 0 ]; + u[ 0 ] = c[ 0 ]; + for ( int i = 0; i < N - 2; i++ ) + { + l[ i ] = b[ i ] / d[ i ]; + d[ i + 1 ] = a[ i + 1 ] - l[ i ] * u[ i ]; + u[ i + 1 ] = c[ i + 1 ]; + } + l[ N - 2 ] = b[ N - 2 ] / d[ N - 2 ]; + d[ N - 1 ] = a[ N - 1 ] - l[ N - 2 ] * u[ N - 2 ]; + /* Forward Substitution [L][y] = [q] */ + y[ 0 ] = q[ 0 ]; + for ( int i = 1; i < N; i++ ) + { + y[ i ] = q[ i ] - l[ i - 1 ] * y[ i - 1 ]; + } + /* Backward Substitution [U][x] = [y] */ + x[ N - 1 ] = y[ N - 1 ] / d[ N - 1 ]; + for ( int i = N - 2; i >= 0; i-- ) + { + x[ i ] = ( y[ i ] - u[ i ] * x[ i + 1 ] ) / d[ i ]; + } + delete[] l; + delete[] u; + delete[] d; + delete[] y; + return; +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + std::vector & d ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double r = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + d_star[ i ] = r * ( d[ i ] - a[ i ] * d_star[ i - 1 ] ); + c_star[ i ] = r * c[ i ]; + } + + d[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + d[ i ] = d_star[ i ] - c_star[ i ] * d[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + std::vector a{ 0, -1, -1, -1, -1 }; + std::vector b{ 2, 2, 2, 2, 2 }; + std::vector c{ -1, -1, -1, -1, 0 }; + std::vector d{ 1.0, 1.0, 1.0, 1.0, 1.0 }; + std::vector q = d; + + std::vector x( q.size() ); + + Print( d, "d" ); + thomas_algorithm( a, b, c, d ); + Print( d, "results" ); + + int N = a.size(); + ThomasAlgorithm( N, a.data(),b.data(), c.data(), x.data(), q.data() ); + Print( x, "x" ); + Print( q, "q" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/serial/02a/CMakeLists.txt b/example/numerical/tdma/cpp/serial/02a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/02a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/serial/02a/main.cpp b/example/numerical/tdma/cpp/serial/02a/main.cpp new file mode 100644 index 00000000..8e3ffed3 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/02a/main.cpp @@ -0,0 +1,176 @@ +import std; + +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void ThomasAlgorithm( int N, double * b, double * a, double * c, double * x, double * q ) +{ + double *l,*u,*d,*y; + l = new double[ N ]; + u = new double[ N ]; + d = new double[ N ]; + y = new double[ N ]; + /* LU Decomposition */ + d[ 0 ] = a[ 0 ]; + u[ 0 ] = c[ 0 ]; + for ( int i = 1; i < N - 1; i++ ) + { + l[ i ] = b[ i ] / d[ i - 1 ]; + d[ i ] = a[ i ] - l[ i ] * u[ i - 1 ]; + u[ i ] = c[ i ]; + } + l[ N - 1 ] = b[ N - 1 ] / d[ N - 2 ]; + d[ N - 1 ] = a[ N - 1 ] - l[ N - 1 ] * u[ N - 2 ]; + /* Forward Substitution [L][y] = [q] */ + y[ 0 ] = q[ 0 ]; + for ( int i = 1; i < N; i++ ) + { + y[ i ] = q[ i ] - l[ i ] * y[ i - 1 ]; + } + /* Backward Substitution [U][x] = [y] */ + x[ N - 1 ] = y[ N - 1 ] / d[ N - 1 ]; + for ( int i = N - 2; i >= 0; i-- ) + { + x[ i ] = ( y[ i ] - u[ i ] * x[ i + 1 ] ) / d[ i ]; + } + delete[] l; + delete[] u; + delete[] d; + delete[] y; + return; +} + +void ThomasAlgorithmVersion1( int N, double * b, double * a, double * c, double * x, double * q ) +{ + double *l,*u,*d,*y; + l = new double[ N ]; + u = new double[ N ]; + d = new double[ N ]; + y = new double[ N ]; + /* LU Decomposition */ + d[ 0 ] = a[ 0 ]; + u[ 0 ] = c[ 0 ]; + + for ( int i = 1; i < N - 1; i++ ) + { + l[ i - 1 ] = b[ i - 1 ] / d[ i - 1 ]; + d[ i ] = a[ i ] - l[ i - 1 ] * u[ i - 1 ]; + u[ i ] = c[ i ]; + } + l[ N - 2 ] = b[ N - 2 ] / d[ N - 2 ]; + d[ N - 1 ] = a[ N - 1 ] - l[ N - 2 ] * u[ N - 2 ]; + /* Forward Substitution [L][y] = [q] */ + y[ 0 ] = q[ 0 ]; + for ( int i = 1; i < N; i++ ) + { + y[ i ] = q[ i ] - l[ i - 1 ] * y[ i - 1 ]; + } + /* Backward Substitution [U][x] = [y] */ + x[ N - 1 ] = y[ N - 1 ] / d[ N - 1 ]; + for ( int i = N - 2; i >= 0; i-- ) + { + x[ i ] = ( y[ i ] - u[ i ] * x[ i + 1 ] ) / d[ i ]; + } + delete[] l; + delete[] u; + delete[] d; + delete[] y; + return; +} + +void ThomasAlgorithmBAK( int N, double * b, double * a, double * c, double * x, double * q ) +{ + double *l,*u,*d,*y; + l = new double[ N ]; + u = new double[ N ]; + d = new double[ N ]; + y = new double[ N ]; + /* LU Decomposition */ + d[ 0 ] = a[ 0 ]; + u[ 0 ] = c[ 0 ]; + for ( int i = 0; i < N - 2; i++ ) + { + l[ i ] = b[ i ] / d[ i ]; + d[ i + 1 ] = a[ i + 1 ] - l[ i ] * u[ i ]; + u[ i + 1 ] = c[ i + 1 ]; + } + l[ N - 2 ] = b[ N - 2 ] / d[ N - 2 ]; + d[ N - 1 ] = a[ N - 1 ] - l[ N - 2 ] * u[ N - 2 ]; + /* Forward Substitution [L][y] = [q] */ + y[ 0 ] = q[ 0 ]; + for ( int i = 1; i < N; i++ ) + { + y[ i ] = q[ i ] - l[ i - 1 ] * y[ i - 1 ]; + } + /* Backward Substitution [U][x] = [y] */ + x[ N - 1 ] = y[ N - 1 ] / d[ N - 1 ]; + for ( int i = N - 2; i >= 0; i-- ) + { + x[ i ] = ( y[ i ] - u[ i ] * x[ i + 1 ] ) / d[ i ]; + } + delete[] l; + delete[] u; + delete[] d; + delete[] y; + return; +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + std::vector & d ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double r = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + d_star[ i ] = r * ( d[ i ] - a[ i ] * d_star[ i - 1 ] ); + c_star[ i ] = r * c[ i ]; + } + + d[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + d[ i ] = d_star[ i ] - c_star[ i ] * d[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + std::vector a{ 0, -1, -1, -1, -1 }; + std::vector b{ 2, 2, 2, 2, 2 }; + std::vector c{ -1, -1, -1, -1, 0 }; + std::vector d{ 1.0, 1.0, 1.0, 1.0, 1.0 }; + std::vector q = d; + + std::vector x( q.size() ); + + Print( d, "d" ); + thomas_algorithm( a, b, c, d ); + Print( d, "results" ); + + int N = a.size(); + ThomasAlgorithm( N, a.data(),b.data(), c.data(), x.data(), q.data() ); + Print( x, "x" ); + Print( q, "q" ); + + ThomasAlgorithmVersion1( N, a.data(), b.data(), c.data(), x.data(), q.data() ); + Print( x, "xVersion1" ); + + return 0; +} diff --git a/example/numerical/tdma/cpp/serial/03/CMakeLists.txt b/example/numerical/tdma/cpp/serial/03/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/03/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/serial/03/main.cpp b/example/numerical/tdma/cpp/serial/03/main.cpp new file mode 100644 index 00000000..168d3f98 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/03/main.cpp @@ -0,0 +1,201 @@ +import std; + +template +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::print( "{:4.1f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + +void FillA( const std::vector &a, + const std::vector &b, + const std::vector &c, + std::vector> &A ) +{ + int N = a.size(); + A.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + if ( i >= 1 ) + { + A[ i ][ i - 1 ] = a[ i ]; + } + A[ i ][ i ] = b[ i ]; + if ( i < N - 1 ) + { + A[ i ][ i + 1 ] = c[ i ]; + } + } +} + +void ThomasAlgorithm( int N, double * b, double * a, double * c, double * x, double * q ) +{ + double *l,*u,*d,*y; + l = new double[ N ]; + u = new double[ N ]; + d = new double[ N ]; + y = new double[ N ]; + /* LU Decomposition */ + d[ 0 ] = a[ 0 ]; + u[ 0 ] = c[ 0 ]; + for ( int i = 1; i < N - 1; i++ ) + { + l[ i ] = b[ i ] / d[ i - 1 ]; + d[ i ] = a[ i ] - l[ i ] * u[ i - 1 ]; + u[ i ] = c[ i ]; + } + l[ N - 1 ] = b[ N - 1 ] / d[ N - 2 ]; + d[ N - 1 ] = a[ N - 1 ] - l[ N - 1 ] * u[ N - 2 ]; + /* Forward Substitution [L][y] = [q] */ + y[ 0 ] = q[ 0 ]; + for ( int i = 1; i < N; i++ ) + { + y[ i ] = q[ i ] - l[ i ] * y[ i - 1 ]; + } + /* Backward Substitution [U][x] = [y] */ + x[ N - 1 ] = y[ N - 1 ] / d[ N - 1 ]; + for ( int i = N - 2; i >= 0; i-- ) + { + x[ i ] = ( y[ i ] - u[ i ] * x[ i + 1 ] ) / d[ i ]; + } + delete[] l; + delete[] u; + delete[] d; + delete[] y; + return; +} + +void ThomasAlgorithmLU(int N, double *b, double *a, double *c, + double *l, double *u, double *d) +{ + /* LU Decomposition */ + d[ 0 ] = a[ 0 ]; + u[ 0 ] = c[ 0 ]; + for ( int i = 0; i < N - 2; i++ ) + { + l[ i ] = b[ i ] / d[ i ]; + d[ i + 1 ] = a[ i + 1 ] - l[ i ] * u[ i ]; + u[ i + 1 ] = c[ i + 1 ]; + } + l[ N - 2 ] = b[ N - 2 ] / d[ N - 2 ]; + d[ N - 1 ] = a[ N - 1 ] - l[ N - 2 ] * u[ N - 2 ]; + return; +} + +void ThomasAlgorithmSolve(int N, double *l, double *u, double *d, + double *x, double *q) +{ + double * y = new double[ N ]; + /* Forward Substitution [L][y] = [q] */ + y[ 0 ] = q[ 0 ]; + for ( int i = 1; i < N; i++ ) + { + y[ i ] = q[ i ] - l[ i - 1 ] * y[ i - 1 ]; + } + /* Backward Substitution [U][x] = [y] */ + x[ N - 1 ] = y[ N - 1 ] / d[ N - 1 ]; + for ( int i = N - 2; i >= 0; i-- ) + { + x[ i ] = ( y[ i ] - u[ i ] * x[ i + 1 ] ) / d[ i ]; + } + delete[] y; + return; +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + std::vector & d ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double r = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + d_star[ i ] = r * ( d[ i ] - a[ i ] * d_star[ i - 1 ] ); + c_star[ i ] = r * c[ i ]; + } + + d[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + d[ i ] = d_star[ i ] - c_star[ i ] * d[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + std::vector a{ 0, -1, -1, -1, -1 }; + std::vector b{ 2, 2, 2, 2, 2 }; + std::vector c{ -1, -1, -1, -1, 0 }; + std::vector d{ 1.0, 1.0, 1.0, 1.0, 1.0 }; + std::vector q = d; + + std::vector x( q.size() ); + std::vector> AA; + FillA( a, b, c, AA ); + Print( AA, "AA" ); + + Print( d, "d" ); + thomas_algorithm( a, b, c, d ); + Print( d, "results" ); + + int N = a.size(); + ThomasAlgorithm( N, a.data(),b.data(), c.data(), x.data(), q.data() ); + Print( x, "x" ); + Print( q, "q" ); + + ThomasAlgorithmVersion1( N, a.data(), b.data(), c.data(), x.data(), q.data() ); + Print( x, "xVersion1" ); + + std::vector y( q.size() ); + MatrixMultiply( AA, x, y ); + Print( y, "y" ); + + std::vector y1( q.size() ); + MatrixMultiply( AA, d, y1 ); + Print( y1, "y1" ); + + + return 0; +} diff --git a/example/numerical/tdma/cpp/serial/03a/CMakeLists.txt b/example/numerical/tdma/cpp/serial/03a/CMakeLists.txt new file mode 100644 index 00000000..c4ffb391 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/03a/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.31) +project(testprj) + +set ( PRJ_COMPILE_FEATURES ) + +if ( MSVC ) + set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME} ) +endif() + +list ( APPEND PRJ_COMPILE_FEATURES cxx_std_23 ) + +add_executable( ${PROJECT_NAME} ) + +target_sources( ${PROJECT_NAME} + PRIVATE + main.cpp +) + +target_compile_features ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_FEATURES} +) + +target_compile_definitions ( ${PROJECT_NAME} + PRIVATE + ${PRJ_COMPILE_DEFINITIONS} +) \ No newline at end of file diff --git a/example/numerical/tdma/cpp/serial/03a/main.cpp b/example/numerical/tdma/cpp/serial/03a/main.cpp new file mode 100644 index 00000000..1a26e530 --- /dev/null +++ b/example/numerical/tdma/cpp/serial/03a/main.cpp @@ -0,0 +1,196 @@ +import std; + +template +void Print( std::vector & x, const std::string & name = "vector" ) +{ + std::print( "{} = ", name ); + for ( auto v: x ) + { + std::print( "{} ", v ); + } + std::println(); +} + +void Print( std::vector> & a, const std::string & name = "matrix" ) +{ + int NI = a.size(); + for ( int i = 0; i < NI; ++ i ) + { + int NJ = a[ i ].size(); + for ( int j = 0; j < NJ; ++ j ) + { + std::print( "{:4.1f} ", a[ i ][ j ] ); + } + std::println(); + } + std::println(); +} + +void MatrixMultiply( std::vector> & a, std::vector & x, std::vector & y ) +{ + int N = a.size(); + for ( int i = 0; i < N; ++ i ) + { + y[ i ] = 0.0; + for ( int j = 0; j < N; ++ j ) + { + y[ i ] += a[ i ][ j ] * x[ j ]; + } + } +} + +void FillA( const std::vector &a, + const std::vector &b, + const std::vector &c, + std::vector> &A ) +{ + int N = a.size(); + A.resize( N ); + for ( int i = 0; i < N; ++ i ) + { + A[ i ].resize( N ); + if ( i >= 1 ) + { + A[ i ][ i - 1 ] = a[ i ]; + } + A[ i ][ i ] = b[ i ]; + if ( i < N - 1 ) + { + A[ i ][ i + 1 ] = c[ i ]; + } + } +} + +void ThomasAlgorithm( int N, double * b, double * a, double * c, double * x, double * q ) +{ + double *l,*u,*d,*y; + l = new double[ N ]; + u = new double[ N ]; + d = new double[ N ]; + y = new double[ N ]; + /* LU Decomposition */ + d[ 0 ] = a[ 0 ]; + u[ 0 ] = c[ 0 ]; + for ( int i = 1; i < N - 1; i++ ) + { + l[ i ] = b[ i ] / d[ i - 1 ]; + d[ i ] = a[ i ] - l[ i ] * u[ i - 1 ]; + u[ i ] = c[ i ]; + } + l[ N - 1 ] = b[ N - 1 ] / d[ N - 2 ]; + d[ N - 1 ] = a[ N - 1 ] - l[ N - 1 ] * u[ N - 2 ]; + /* Forward Substitution [L][y] = [q] */ + y[ 0 ] = q[ 0 ]; + for ( int i = 1; i < N; i++ ) + { + y[ i ] = q[ i ] - l[ i ] * y[ i - 1 ]; + } + /* Backward Substitution [U][x] = [y] */ + x[ N - 1 ] = y[ N - 1 ] / d[ N - 1 ]; + for ( int i = N - 2; i >= 0; i-- ) + { + x[ i ] = ( y[ i ] - u[ i ] * x[ i + 1 ] ) / d[ i ]; + } + delete[] l; + delete[] u; + delete[] d; + delete[] y; + return; +} + +void ThomasAlgorithmLU(int N, double *b, double *a, double *c, + double *l, double *u, double *d) +{ + /* LU Decomposition */ + d[ 0 ] = a[ 0 ]; + u[ 0 ] = c[ 0 ]; + for ( int i = 1; i < N -1; i++ ) + { + l[ i ] = b[ i ] / d[ i - 1 ]; + d[ i ] = a[ i ] - l[ i ] * u[ i - 1 ]; + u[ i ] = c[ i ]; + } + l[ N - 1 ] = b[ N - 1 ] / d[ N - 2 ]; + d[ N - 1 ] = a[ N - 1 ] - l[ N - 1 ] * u[ N - 2 ]; + return; +} + +void ThomasAlgorithmSolve(int N, double *l, double *u, double *d, + double *x, double *q) +{ + double * y = new double[ N ]; + /* Forward Substitution [L][y] = [q] */ + y[ 0 ] = q[ 0 ]; + for ( int i = 1; i < N; i++ ) + { + y[ i ] = q[ i ] - l[ i ] * y[ i - 1 ]; + } + /* Backward Substitution [U][x] = [y] */ + x[ N - 1 ] = y[ N - 1 ] / d[ N - 1 ]; + for ( int i = N - 2; i >= 0; i-- ) + { + x[ i ] = ( y[ i ] - u[ i ] * x[ i + 1 ] ) / d[ i ]; + } + delete[] y; + return; +} + +void thomas_algorithm( const std::vector & a, + const std::vector & b, + const std::vector & c, + std::vector & d ) +{ + size_t N = d.size(); + + std::vector c_star( N, 0.0 ); + std::vector d_star( N, 0.0 ); + + c_star[ 0 ] = c[ 0 ] / b[ 0 ]; + d_star[ 0 ] = d[ 0 ] / b[ 0 ]; + + for ( int i = 1; i < N; ++ i ) + { + double r = 1.0 / ( b[ i ] - a[ i ] * c_star[ i - 1 ] ); + d_star[ i ] = r * ( d[ i ] - a[ i ] * d_star[ i - 1 ] ); + c_star[ i ] = r * c[ i ]; + } + + d[ N - 1 ] = d_star[ N - 1 ]; + + for ( int i = N - 2; i >= 0; -- i ) + { + d[ i ] = d_star[ i ] - c_star[ i ] * d[ i + 1 ]; + } +} + +int main( int argc, char ** argv ) +{ + std::vector a{ 0, -1, -1, -1, -1 }; + std::vector b{ 2, 2, 2, 2, 2 }; + std::vector c{ -1, -1, -1, -1, 0 }; + std::vector q{ 1.0, 1.0, 1.0, 1.0, 1.0 }; + + std::vector x( q.size() ); + std::vector> AA; + FillA( a, b, c, AA ); + Print( AA, "AA" ); + + int N = a.size(); + ThomasAlgorithm( N, a.data(),b.data(), c.data(), x.data(), q.data() ); + Print( x, "x" ); + + std::vector y( q.size() ); + MatrixMultiply( AA, x, y ); + Print( y, "y" ); + + std::vector l( q.size() ); + std::vector u( q.size() ); + std::vector d( q.size() ); + std::vector xx( q.size() ); + + ThomasAlgorithmLU( N, a.data(), b.data(), c.data(), l.data(), u.data(), d.data() ); + ThomasAlgorithmSolve( N, l.data(), u.data(), d.data(), xx.data(), q.data() ); + Print( xx, "xx" ); + + return 0; +} diff --git a/example/numerical/tdma/01/tdma.py b/example/numerical/tdma/python/01/tdma.py similarity index 100% rename from example/numerical/tdma/01/tdma.py rename to example/numerical/tdma/python/01/tdma.py diff --git a/example/numerical/thomas_algorithm/01/CMakeLists.txt b/example/numerical/thomas_algorithm/01/CMakeLists.txt new file mode 100644 index 00000000..79522996 --- /dev/null +++ b/example/numerical/thomas_algorithm/01/CMakeLists.txt @@ -0,0 +1,72 @@ +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 () + +list ( APPEND PRJ_LIBRARIES MPI::MPI_C ) + +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 +) + +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/numerical/thomas_algorithm/01/main.cpp b/example/numerical/thomas_algorithm/01/main.cpp new file mode 100644 index 00000000..f8c5c875 --- /dev/null +++ b/example/numerical/thomas_algorithm/01/main.cpp @@ -0,0 +1,56 @@ +#include +#include +#include + +void thomas_algorithm(double* a, double* b, double* c, double* d, double* x, int n) { + // ǰÏòÏûÔª + for (int i = 1; i < n; ++i) { + double w = a[i - 1] / b[i - 1]; + b[i] -= w * c[i - 1]; + d[i] -= w * d[i - 1]; + } + + // ºóÏòÌæ´ú + x[n - 1] = d[n - 1] / b[n - 1]; + for (int i = n - 2; i >= 0; --i) { + x[i] = (d[i] - c[i] * x[i + 1]) / b[i]; + } +} + +int main(int argc, char** argv) { + MPI_Init(&argc, &argv); + + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + const int n = 6; // ¼ÙÉè¾ØÕó´óСΪ6 + double a[n - 1] = { -1, -1, -1, -1, -1 }; // ϶ԽÇÏß + double b[n] = { 2, 2, 2, 2, 2, 2 }; // Ö÷¶Ô½ÇÏß + double c[n - 1] = { -1, -1, -1, -1, -1 }; // É϶ԽÇÏß + double d[n] = { 1, 0, 0, 0, 0, 1 }; // Óұߵij£ÊýÏòÁ¿ + double x[n]; // ½á¹ûÏòÁ¿ + + // ½«ÎÊÌâ»®·Ö¸ø¸÷¸ö½ø³Ì + int local_n = n / size; // ÿ¸ö½ø³Ì´¦ÀíµÄÌõÄ¿ÊýÁ¿£¬¼ÙÉèn¿ÉÒÔ±»sizeÕû³ý + + // ÕâÀï¼ÙÉèÿ¸ö´¦ÀíÆ÷Ö»¼ÆËã¹Ì¶¨µÄÒ»²¿·Ö + // ½øÐв¢ÐеÄǰÏòÏûÔª + for (int i = 0; i < size; ++i) { + if (rank == i) { + thomas_algorithm(a + i * local_n, b + i * local_n, c + i * local_n, d + i * local_n, x + i * local_n, local_n); + } + MPI_Bcast(x, n, MPI_DOUBLE, i, MPI_COMM_WORLD); // ¹ã²¥½á¹û + } + + if (rank == 0) { + std::cout << "Solution: "; + for (int i = 0; i < n; ++i) { + std::cout << x[i] << " "; + } + std::cout << std::endl; + } + + MPI_Finalize(); + return 0; +} \ No newline at end of file diff --git a/example/partition/struct/1d-bugers/1to2blocks/01/CMakeLists.txt b/example/partition/struct/1d-bugers/1to2blocks/01/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/1d-bugers/1to2blocks/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-bugers/1to2blocks/01/CgnsGrid.cpp b/example/partition/struct/1d-bugers/1to2blocks/01/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/1d-bugers/1to2blocks/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-bugers/1to2blocks/01/CgnsGrid.h b/example/partition/struct/1d-bugers/1to2blocks/01/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/1d-bugers/1to2blocks/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-bugers/1to2blocks/01/Partition.cpp b/example/partition/struct/1d-bugers/1to2blocks/01/Partition.cpp new file mode 100644 index 00000000..d5811c41 --- /dev/null +++ b/example/partition/struct/1d-bugers/1to2blocks/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->nProc = 2; + this->inputName = "../burgers1d1blocksv1.cgns"; + this->outName = std::format( "../burgers1d{}blocks.cgns", this->nProc ); +} + +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->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-bugers/1to2blocks/01/Partition.h b/example/partition/struct/1d-bugers/1to2blocks/01/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/1d-bugers/1to2blocks/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-bugers/1to2blocks/01/README.txt b/example/partition/struct/1d-bugers/1to2blocks/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d-bugers/1to2blocks/01/README.txt @@ -0,0 +1 @@ +cmake -DCMAKE_TOOLCHAIN_FILE="c:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" .. diff --git a/example/partition/struct/1d-bugers/1to2blocks/01/SplitZone.cpp b/example/partition/struct/1d-bugers/1to2blocks/01/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/1d-bugers/1to2blocks/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-bugers/1to2blocks/01/SplitZone.h b/example/partition/struct/1d-bugers/1to2blocks/01/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/1d-bugers/1to2blocks/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-bugers/1to2blocks/01/burgers1d1blocksv1.cgns b/example/partition/struct/1d-bugers/1to2blocks/01/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/partition/struct/1d-bugers/1to2blocks/01/burgers1d1blocksv1.cgns differ diff --git a/example/partition/struct/1d-bugers/1to2blocks/01/burgers1d2blocks.cgns b/example/partition/struct/1d-bugers/1to2blocks/01/burgers1d2blocks.cgns new file mode 100644 index 00000000..51518b5c Binary files /dev/null and b/example/partition/struct/1d-bugers/1to2blocks/01/burgers1d2blocks.cgns differ diff --git a/example/partition/struct/1d-bugers/1to2blocks/01/main.cpp b/example/partition/struct/1d-bugers/1to2blocks/01/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d-bugers/1to2blocks/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-bugers/1to4blocks/01/CMakeLists.txt b/example/partition/struct/1d-bugers/1to4blocks/01/CMakeLists.txt new file mode 100644 index 00000000..74ceea7d --- /dev/null +++ b/example/partition/struct/1d-bugers/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-bugers/1to4blocks/01/CgnsGrid.cpp b/example/partition/struct/1d-bugers/1to4blocks/01/CgnsGrid.cpp new file mode 100644 index 00000000..dfe750bd --- /dev/null +++ b/example/partition/struct/1d-bugers/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-bugers/1to4blocks/01/CgnsGrid.h b/example/partition/struct/1d-bugers/1to4blocks/01/CgnsGrid.h new file mode 100644 index 00000000..053c467b --- /dev/null +++ b/example/partition/struct/1d-bugers/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-bugers/1to4blocks/01/Partition.cpp b/example/partition/struct/1d-bugers/1to4blocks/01/Partition.cpp new file mode 100644 index 00000000..78e0e180 --- /dev/null +++ b/example/partition/struct/1d-bugers/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->nProc = 4; + this->inputName = "../burgers1d1blocksv1.cgns"; + this->outName = std::format( "../burgers1d{}blocks.cgns", this->nProc ); +} + +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->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-bugers/1to4blocks/01/Partition.h b/example/partition/struct/1d-bugers/1to4blocks/01/Partition.h new file mode 100644 index 00000000..8a4a9731 --- /dev/null +++ b/example/partition/struct/1d-bugers/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-bugers/1to4blocks/01/README.txt b/example/partition/struct/1d-bugers/1to4blocks/01/README.txt new file mode 100644 index 00000000..13dc2f91 --- /dev/null +++ b/example/partition/struct/1d-bugers/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-bugers/1to4blocks/01/SplitZone.cpp b/example/partition/struct/1d-bugers/1to4blocks/01/SplitZone.cpp new file mode 100644 index 00000000..aef70754 --- /dev/null +++ b/example/partition/struct/1d-bugers/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-bugers/1to4blocks/01/SplitZone.h b/example/partition/struct/1d-bugers/1to4blocks/01/SplitZone.h new file mode 100644 index 00000000..ffe1e306 --- /dev/null +++ b/example/partition/struct/1d-bugers/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-bugers/1to4blocks/01/burgers1d1blocksv1.cgns b/example/partition/struct/1d-bugers/1to4blocks/01/burgers1d1blocksv1.cgns new file mode 100644 index 00000000..36f2b180 Binary files /dev/null and b/example/partition/struct/1d-bugers/1to4blocks/01/burgers1d1blocksv1.cgns differ diff --git a/example/partition/struct/1d-bugers/1to4blocks/01/burgers1d4blocks.cgns b/example/partition/struct/1d-bugers/1to4blocks/01/burgers1d4blocks.cgns new file mode 100644 index 00000000..3585da45 Binary files /dev/null and b/example/partition/struct/1d-bugers/1to4blocks/01/burgers1d4blocks.cgns differ diff --git a/example/partition/struct/1d-bugers/1to4blocks/01/main.cpp b/example/partition/struct/1d-bugers/1to4blocks/01/main.cpp new file mode 100644 index 00000000..5da1de7c --- /dev/null +++ b/example/partition/struct/1d-bugers/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; +}