diff --git a/.github/workflows/buildTest.yml b/.github/workflows/buildTest.yml index cd51250..4fbd899 100644 --- a/.github/workflows/buildTest.yml +++ b/.github/workflows/buildTest.yml @@ -1,11 +1,19 @@ name: build-test-XIOS -on: [push, pull_request] +on: + push: + branches: + - main + pull_request: jobs: build_test: - name: build XIOS and run tests + name: build test runs-on: ubuntu-latest + strategy: + matrix: + # version: [XIOS/trunk@2252, XIOS2/trunk, XIOS3/trunk] + version: [XIOS/trunk@2252, XIOS2/trunk] steps: # Check out repository branch - uses: actions/checkout@v4 @@ -16,19 +24,33 @@ jobs: sudo apt -yq install $(/ p2p<\/variable>/g' generic_testcase/iodef.xml + cat generic_testcase/iodef.xml + fi ./make_xios --job 2 --arch GCC_LINUX_APT - ls -l lib/ - ls -l inc/ - ls -l bin/ cd .. + shell: bash - name: run generic run: | - cd XIOS2/generic_testcase + cd XIOS/generic_testcase ln -s ../bin/generic_testcase.exe ln -s ../bin/xios_server.exe sed -i 's/nb_proc_atm=4/nb_proc_atm=1/g' param.def mpiexec -n 1 ./generic_testcase.exe : -n 1 ./xios_server.exe cd ../.. + - name: run resample example + run: | + . arch/arch-GCC_LINUX_APT.env + . arch/arch-GCC_LINUX_APT.path + export XIOS_BINDIR=$PWD/XIOS/bin + export XIOS_INCDIR=$PWD/XIOS/inc + export XIOS_LIBDIR=$PWD/XIOS/lib + + export MVER=${{ matrix.version }} + + python3 -m unittest discover -v -s xios_examples diff --git a/README.md b/README.md index dd2d40d..f26b906 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,12 @@ # tcd-XIOS-demonstration Demonstration code for XML I/O server XIOS usage. + +Demonstrations of using XIOS are provided with Continuous Integration testing with respect to XIOS2 trunk. + +## Environments + +Environments are managed, with a little complication, to enable running on scientific desktop and on Github Continuous Integration. + +There is a helper script that one can source, in the root directory, to ensure that the scientific desktop LFRic environment is loaded, using the environment variable setup for the Makefiles, which is also compatible with the Github CI runner. + +`. desktopEnv` diff --git a/dependencies b/dependencies index 873554d..f403a22 100644 --- a/dependencies +++ b/dependencies @@ -6,3 +6,5 @@ libnetcdf-mpi-dev libnetcdff-dev libpnetcdf-dev netcdf-bin +python3-numpy +python3-netcdf4 diff --git a/desktopEnv b/desktopEnv index c60e747..5595580 100644 --- a/desktopEnv +++ b/desktopEnv @@ -1,3 +1,8 @@ +# this environment management script needs to be sourced in order to provide +# equivalent functionality on the MO Linux desktop to the Github CI environment. +# `. desktopEnv` + +# Use the LFRic programming environment module purge module unuse /project/ukmo/rhel7/R/modulefiles; module unuse /project/ukmo/rhel7/fortran/opt/gfortran/modulefiles module use /project/extrasoftware/modulefiles.rhel7 @@ -5,11 +10,25 @@ module use /data/users/lfric/software/modulefiles.rhel7 module load environment/lfric/gcc +# provide explit path set to the arch script for netCDF linking export NETCDF_LIB_DIR=$NETCDF_4_8_1_ROOT/lib:$NETCDF_4_8_1_ROOT/lib64 export NETCDF_INC_DIR=$NETCDF_4_8_1_ROOT/include . arch/arch-GCC_LINUX_APT.path +# provide explicit paths to all XIOS components export XIOS_INCDIR=$XIOS_R2252_2_ROOT/include export XIOS_LIBDIR=$XIOS_R2252_2_ROOT/lib -export XIOS_BINDIR=$XIOS_R2252_2_ROOT/bin \ No newline at end of file +export XIOS_BINDIR=$XIOS_R2252_2_ROOT/bin + +# use an extend LFRic Python environment +# that includes netCDF4-python built w.r.t. the LFRIC +# netCDF +. /data/users/itmh/pylfricpyexptl/bin/activate + +# dev-notes (starting from the lfric Python as provided by module) +# - python -m venv {/some/path} +# - python -m pip install cython mpi4py +# - python -m pip install --no-build-isolation netCDF4==1.5.8 +# - pinned version needed for compatability with libnetcdf 4.8.1 +# - . activate {/some/path} diff --git a/patches/xios3/revert_svn2517_transport.patch b/patches/xios3/revert_svn2517_transport.patch new file mode 100644 index 0000000..3f4dd79 --- /dev/null +++ b/patches/xios3/revert_svn2517_transport.patch @@ -0,0 +1,1243 @@ +Index: src/manager/contexts_manager.cpp +=================================================================== +--- src/manager/contexts_manager.cpp (revision 2596) ++++ src/manager/contexts_manager.cpp (working copy) +@@ -26,11 +26,12 @@ + + MPI_Comm_rank(xiosComm_, &commRank) ; + winNotify_ = new CWindowManager(xiosComm_, maxBufferSize_,"CContextsManager::winNotify_") ; +- winNotify_->updateToExclusiveWindow(commRank, this, &CContextsManager::notificationsDumpOut) ; + + + winContexts_ = new CWindowManager(xiosComm_, maxBufferSize_,"CContextsManager::winContexts_") ; +- winContexts_->updateToExclusiveWindow(commRank, this, &CContextsManager::contextsDumpOut) ; ++ winContexts_->lockWindow(commRank,0) ; ++ winContexts_->updateToWindow(commRank, this, &CContextsManager::contextsDumpOut) ; ++ winContexts_->unlockWindow(commRank,0) ; + + MPI_Barrier(xiosComm_) ; + } +@@ -109,7 +110,7 @@ + { + winNotify_->lockWindowExclusive(rank) ; + winNotify_->pushToLockedWindow(rank, this, &CContextsManager::notificationsDumpOut) ; +- winNotify_->unlockWindowExclusive(rank) ; ++ winNotify_->unlockWindow(rank) ; + } + + +@@ -168,7 +169,9 @@ + { + int commRank ; + MPI_Comm_rank(xiosComm_, &commRank) ; +- winNotify_->popFromExclusiveWindow(commRank, this, &CContextsManager::notificationsDumpIn) ; ++ winNotify_->lockWindowExclusive(commRank) ; ++ winNotify_->popFromLockedWindow(commRank, this, &CContextsManager::notificationsDumpIn) ; ++ winNotify_->unlockWindow(commRank) ; + if (notifyType_==NOTIFY_CREATE_CONTEXT) createServerContext() ; + else if (notifyType_==NOTIFY_CREATE_INTERCOMM) createServerContextIntercomm() ; + +@@ -211,7 +214,7 @@ + winContexts_->flushWindow(managerGlobalLeader_) ; + contexts_[fullContextId] = contextInfo ; + winContexts_->updateToLockedWindow(managerGlobalLeader_, this, &CContextsManager::contextsDumpOut) ; +- winContexts_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winContexts_->unlockWindow(managerGlobalLeader_) ; + } + + bool CContextsManager::getContextInfo(const string& fullContextId, SRegisterContextInfo& contextInfo, MPI_Comm comm) +@@ -223,7 +226,9 @@ + if (commRank==0) + { + +- winContexts_->updateFromSharedWindow(managerGlobalLeader_, this, &CContextsManager::contextsDumpIn) ; ++ winContexts_->lockWindowShared(managerGlobalLeader_) ; ++ winContexts_->updateFromLockedWindow(managerGlobalLeader_, this, &CContextsManager::contextsDumpIn) ; ++ winContexts_->unlockWindow(managerGlobalLeader_) ; + + auto it=contexts_.find(fullContextId) ; + if ( it == contexts_.end()) ret=false ; +Index: src/manager/coupler_manager.cpp +=================================================================== +--- src/manager/coupler_manager.cpp (revision 2596) ++++ src/manager/coupler_manager.cpp (working copy) +@@ -22,8 +22,13 @@ + winNextCoupling_ = new CWindowManager(xiosComm_, maxBufferSize_,"CCouplerManager::winNextCoupling_") ; + if (commRank==managerGlobalLeader_) + { +- winRegistredCoupling_->updateToExclusiveWindow(managerGlobalLeader_, this, &CCouplerManager::registredCouplingDumpOut) ; +- winNextCoupling_->updateToExclusiveWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpOut) ; ++ winRegistredCoupling_->lockWindow(managerGlobalLeader_,0) ; ++ winRegistredCoupling_->updateToWindow(managerGlobalLeader_, this, &CCouplerManager::registredCouplingDumpOut) ; ++ winRegistredCoupling_->unlockWindow(managerGlobalLeader_,0) ; ++ ++ winNextCoupling_->lockWindow(managerGlobalLeader_,0) ; ++ winNextCoupling_->updateToWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpOut) ; ++ winNextCoupling_->unlockWindow(managerGlobalLeader_,0) ; + } + + MPI_Barrier(xiosComm_) ; +@@ -41,24 +46,24 @@ + hash strHash ; + size_t key = strHash(getStrCoupling(srcCoupling,dstCoupling)) ; + +- winRegistredCoupling_->lockWindowExclusive(managerGlobalLeader_) ; +- winRegistredCoupling_->updateFromLockedWindow(managerGlobalLeader_, this, &CCouplerManager::registredCouplingDumpIn) ; ++ winRegistredCoupling_->lockWindow(managerGlobalLeader_,0) ; ++ winRegistredCoupling_->updateFromWindow(managerGlobalLeader_, this, &CCouplerManager::registredCouplingDumpIn) ; + if (registredCoupling_.count(key)==1) + { + registredCoupling_.erase(key) ; +- winRegistredCoupling_->updateToLockedWindow(managerGlobalLeader_, this, &CCouplerManager::registredCouplingDumpOut) ; +- winNextCoupling_->lockWindowExclusive(managerGlobalLeader_) ; +- winNextCoupling_->updateFromLockedWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpIn) ; ++ winRegistredCoupling_->updateToWindow(managerGlobalLeader_, this, &CCouplerManager::registredCouplingDumpOut) ; ++ winNextCoupling_->lockWindow(managerGlobalLeader_,0) ; ++ winNextCoupling_->updateFromWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpIn) ; + nextCoupling_.push_back(pair(key,2)) ; +- winNextCoupling_->updateToLockedWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpOut) ; +- winNextCoupling_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winNextCoupling_->updateToWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpOut) ; ++ winNextCoupling_->unlockWindow(managerGlobalLeader_,0) ; + } + else + { + registredCoupling_.insert(key) ; +- winRegistredCoupling_->updateToLockedWindow(managerGlobalLeader_, this, &CCouplerManager::registredCouplingDumpOut) ; ++ winRegistredCoupling_->updateToWindow(managerGlobalLeader_, this, &CCouplerManager::registredCouplingDumpOut) ; + } +- winRegistredCoupling_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winRegistredCoupling_->unlockWindow(managerGlobalLeader_,0) ; + } + + bool CCouplerManager::isNextCoupling(string srcCoupling, string dstCoupling) +@@ -67,17 +72,17 @@ + hash strHash ; + size_t key = strHash(getStrCoupling(srcCoupling,dstCoupling)) ; + +- winNextCoupling_->lockWindowExclusive(managerGlobalLeader_) ; +- winNextCoupling_->updateFromLockedWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpIn) ; ++ winNextCoupling_->lockWindow(managerGlobalLeader_,0) ; ++ winNextCoupling_->updateFromWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpIn) ; + if (nextCoupling_.front().first==key) + { + ret=true ; + if (nextCoupling_.front().second==1) nextCoupling_.pop_front() ; + else nextCoupling_.front().second=1 ; +- winNextCoupling_->updateToLockedWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpOut) ; ++ winNextCoupling_->updateToWindow(managerGlobalLeader_, this, &CCouplerManager::nextCouplingDumpOut) ; + } + else ret=false ; +- winNextCoupling_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winNextCoupling_->unlockWindow(managerGlobalLeader_,0) ; + return ret ; + } + void CCouplerManager::registredCouplingDumpOut(CBufferOut& buffer) +@@ -123,4 +128,4 @@ + } + } + +-} +\ No newline at end of file ++} +Index: src/manager/pool_ressource.cpp +=================================================================== +--- src/manager/pool_ressource.cpp (revision 2596) ++++ src/manager/pool_ressource.cpp (working copy) +@@ -29,7 +29,9 @@ + } + + notifyType_=NOTIFY_NOTHING; +- winNotify_->updateToExclusiveWindow(commRank, this, &CPoolRessource::notificationsDumpOut) ; ++ winNotify_->lockWindow(commRank,0) ; ++ winNotify_->updateToWindow(commRank, this, &CPoolRessource::notificationsDumpOut) ; ++ winNotify_->unlockWindow(commRank,0) ; + MPI_Barrier(poolComm_) ; + if (eventScheduler) eventScheduler_=eventScheduler ; + else eventScheduler_= make_shared(poolComm) ; +@@ -132,14 +134,18 @@ + + void CPoolRessource::sendNotification(int rank) + { +- winNotify_->pushToExclusiveWindow(rank, this, &CPoolRessource::notificationsDumpOut) ; ++ winNotify_->lockWindowExclusive(rank) ; ++ winNotify_->pushToLockedWindow(rank, this, &CPoolRessource::notificationsDumpOut) ; ++ winNotify_->unlockWindow(rank) ; + } + + void CPoolRessource::checkNotifications(void) + { + int commRank ; + MPI_Comm_rank(poolComm_, &commRank) ; +- winNotify_->popFromExclusiveWindow(commRank, this, &CPoolRessource::notificationsDumpIn) ; ++ winNotify_->lockWindowExclusive(commRank) ; ++ winNotify_->popFromLockedWindow(commRank, this, &CPoolRessource::notificationsDumpIn) ; ++ winNotify_->unlockWindow(commRank) ; + if (notifyType_==NOTIFY_CREATE_SERVICE) + { + if (CThreadManager::isUsingThreads()) synchronize() ; +Index: src/manager/ressources_manager.cpp +=================================================================== +--- src/manager/ressources_manager.cpp (revision 2596) ++++ src/manager/ressources_manager.cpp (working copy) +@@ -49,7 +49,9 @@ + { + info(40)<<"CRessourcesManager::createPool : calling createPool : "<updateFromExclusiveWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + + notifyType_=NOTIFY_CREATE_POOL ; + notifyCreatePool_=make_tuple(poolId, size) ; +@@ -59,7 +61,9 @@ + + void CRessourcesManager::finalize(void) + { +- winRessources_->updateFromExclusiveWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + + if (serverLeader_!=-1) + { +@@ -73,7 +77,7 @@ + { + winNotify_->lockWindowExclusive(rank) ; + winNotify_->pushToLockedWindow(rank, this, &CRessourcesManager::notificationsDumpOut) ; +- winNotify_->unlockWindowExclusive(rank) ; ++ winNotify_->unlockWindow(rank) ; + } + + +@@ -135,7 +139,7 @@ + winNotify_->popFromLockedWindow(commRank, this, &CRessourcesManager::notificationsDumpIn) ; + CTimer::get("CRessourcesManager::checkNotifications pop").suspend(); + CTimer::get("CRessourcesManager::checkNotifications unlock").resume(); +- winNotify_->unlockWindowExclusive(commRank) ; ++ winNotify_->unlockWindow(commRank) ; + CTimer::get("CRessourcesManager::checkNotifications unlock").suspend(); + if (notifyType_==NOTIFY_CREATE_POOL) createPool() ; + else if (notifyType_==NOTIFY_FINALIZE) finalizeSignal() ; +@@ -192,46 +196,48 @@ + + void CRessourcesManager::registerServerLeader(int serverLeaderRank) + { +- winRessources_->lockWindowExclusive(managerGlobalLeader_) ; +- winRessources_->updateFromLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; + serverLeader_ = serverLeaderRank ; +- winRessources_->updateToLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; +- winRessources_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winRessources_->updateToWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + } + + void CRessourcesManager::registerRessourcesSize(int size) + { +- winRessources_->lockWindowExclusive(managerGlobalLeader_) ; +- winRessources_->updateFromLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; + ressourcesSize_ = size ; + freeRessourcesSize_ = size ; +- winRessources_->updateToLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; +- winRessources_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winRessources_->updateToWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + } + + + void CRessourcesManager::registerPoolClient(const string& poolId, int size, int leader) + { +- winRessources_->lockWindowExclusive(managerGlobalLeader_) ; +- winRessources_->updateFromLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; + pools_[poolId] = make_tuple(size, size, leader) ; +- winRessources_->updateToLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; +- winRessources_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winRessources_->updateToWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + } + + void CRessourcesManager::registerPoolServer(const string& poolId, int size, int leader) + { +- winRessources_->lockWindowExclusive(managerGlobalLeader_) ; +- winRessources_->updateFromLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; + pools_[poolId] = make_tuple(size, size, leader) ; + freeRessourcesSize_-=size ; +- winRessources_->updateToLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; +- winRessources_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winRessources_->updateToWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + } + + bool CRessourcesManager::getPoolInfo(const string& poolId, int& size, int& freeSize, int& leader) + { +- winRessources_->updateFromSharedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + + auto it=pools_.find(poolId) ; + if ( it == pools_.end()) return false ; +@@ -248,8 +254,8 @@ + { + bool ret ; + +- winRessources_->lockWindowExclusive(managerGlobalLeader_) ; +- winRessources_->updateFromLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; + + + auto it=pools_.find(poolId) ; +@@ -260,22 +266,26 @@ + get<1>(it->second)-=size ; + ret=true ; + } +- winRessources_->updateToLockedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; +- winRessources_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winRessources_->updateToWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpOut) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + + return ret ; + } + + int CRessourcesManager::getRessourcesSize(void) + { +- winRessources_->updateFromSharedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + + return ressourcesSize_ ; + } + + int CRessourcesManager::getFreeRessourcesSize(void) + { +- winRessources_->updateFromSharedWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->lockWindow(managerGlobalLeader_,0) ; ++ winRessources_->updateFromWindow(managerGlobalLeader_, this, &CRessourcesManager::ressourcesDumpIn) ; ++ winRessources_->unlockWindow(managerGlobalLeader_,0) ; + + return freeRessourcesSize_ ; + } +Index: src/manager/server_context.cpp +=================================================================== +--- src/manager/server_context.cpp (revision 2596) ++++ src/manager/server_context.cpp (working copy) +@@ -161,7 +161,9 @@ + + void CServerContext::sendNotification(int rank) + { +- winNotify_->pushToExclusiveWindow(rank, this, &CServerContext::notificationsDumpOut) ; ++ winNotify_->lockWindowExclusive(rank) ; ++ winNotify_->pushToLockedWindow(rank, this, &CServerContext::notificationsDumpOut) ; ++ winNotify_->unlockWindow(rank) ; + } + + +@@ -200,7 +202,9 @@ + { + int commRank ; + MPI_Comm_rank(contextComm_, &commRank) ; +- winNotify_->popFromExclusiveWindow(commRank, this, &CServerContext::notificationsDumpIn) ; ++ winNotify_->lockWindowExclusive(commRank) ; ++ winNotify_->popFromLockedWindow(commRank, this, &CServerContext::notificationsDumpIn) ; ++ winNotify_->unlockWindow(commRank) ; + + if (notifyInType_!= NOTIFY_NOTHING) + { +Index: src/manager/servers_ressource.cpp +=================================================================== +--- src/manager/servers_ressource.cpp (revision 2596) ++++ src/manager/servers_ressource.cpp (working copy) +@@ -87,7 +87,9 @@ + + void CServersRessource::sendNotification(int rank) + { +- winNotify_->pushToExclusiveWindow(rank, this, &CServersRessource::notificationsDumpOut) ; ++ winNotify_->lockWindow(rank,0) ; ++ winNotify_->pushToWindow(rank, this, &CServersRessource::notificationsDumpOut) ; ++ winNotify_->unlockWindow(rank,0) ; + } + + +@@ -189,7 +191,9 @@ + { + int commRank ; + MPI_Comm_rank(serverComm_, &commRank) ; +- winNotify_->popFromExclusiveWindow(commRank, this, &CServersRessource::notificationsDumpIn) ; ++ winNotify_->lockWindow(commRank,0) ; ++ winNotify_->popFromWindow(commRank, this, &CServersRessource::notificationsDumpIn) ; ++ winNotify_->unlockWindow(commRank,0) ; + if (notifyInType_==NOTIFY_CREATE_POOL) + { + if (CThreadManager::isUsingThreads()) synchronize() ; +Index: src/manager/services.cpp +=================================================================== +--- src/manager/services.cpp (revision 2596) ++++ src/manager/services.cpp (working copy) +@@ -28,7 +28,9 @@ + MPI_Comm_rank(serviceComm_,&localRank) ; + + winNotify_ = new CWindowManager(serviceComm_, maxBufferSize_,"CService::winNotify_") ; +- winNotify_->updateToExclusiveWindow(localRank, this, &CService::createContextDumpOut) ; ++ winNotify_->lockWindow(localRank,0) ; ++ winNotify_->updateToWindow(localRank, this, &CService::createContextDumpOut) ; ++ winNotify_->unlockWindow(localRank,0) ; + MPI_Barrier(serviceComm_) ; + if (localRank==localLeader_) + { +@@ -48,7 +50,7 @@ + + CService::~CService() + { +- delete winNotify_ ; ++ //delete winNotify_ ; + for(auto& it : contexts_) delete it.second ; + } + +@@ -75,11 +77,11 @@ + */ + void CService::createContextNotify(int rank, const std::string& poolId, const std::string& serviceId, const int& partitionId, const std::string& contextId) + { +- winNotify_->lockWindowExclusive(rank) ; +- winNotify_->updateFromLockedWindow(rank, this, &CService::createContextDumpIn) ; ++ winNotify_->lockWindow(rank,0) ; ++ winNotify_->updateFromWindow(rank, this, &CService::createContextDumpIn) ; + notifications_.push_back(std::make_tuple(poolId, serviceId, partitionId, contextId)) ; +- winNotify_->updateToLockedWindow(rank, this, &CService::createContextDumpOut) ; +- winNotify_->unlockWindowExclusive(rank) ; ++ winNotify_->updateToWindow(rank, this, &CService::createContextDumpOut) ; ++ winNotify_->unlockWindow(rank,0) ; + } + + +@@ -188,7 +190,9 @@ + + void CService::sendNotification(int rank) + { +- winNotify_->pushToExclusiveWindow(rank, this, &CService::notificationsDumpOut) ; ++ winNotify_->lockWindowExclusive(rank) ; ++ winNotify_->pushToLockedWindow(rank, this, &CService::notificationsDumpOut) ; ++ winNotify_->unlockWindow(rank) ; + } + + +@@ -230,7 +234,9 @@ + { + int commRank ; + MPI_Comm_rank(serviceComm_, &commRank) ; +- winNotify_->popFromExclusiveWindow(commRank, this, &CService::notificationsDumpIn) ; ++ winNotify_->lockWindowExclusive(commRank) ; ++ winNotify_->popFromLockedWindow(commRank, this, &CService::notificationsDumpIn) ; ++ winNotify_->unlockWindow(commRank) ; + + if (notifyInType_!= NOTIFY_NOTHING) + { +@@ -268,17 +274,17 @@ + { + int commRank ; + MPI_Comm_rank(serviceComm_, &commRank) ; +- winNotify_->lockWindowExclusive(commRank) ; +- winNotify_->updateFromLockedWindow(commRank, this, &CService::createContextDumpIn) ; ++ winNotify_->lockWindow(commRank,0) ; ++ winNotify_->updateFromWindow(commRank, this, &CService::createContextDumpIn) ; + + if (!notifications_.empty()) + { + auto info = notifications_.front() ; + createNewContext(get<0>(info), get<1>(info), get<2>(info), get<3>(info)) ; + notifications_.pop_front() ; +- winNotify_->updateToLockedWindow(commRank, this, &CService::createContextDumpOut) ; ++ winNotify_->updateToWindow(commRank, this, &CService::createContextDumpOut) ; + } +- winNotify_->unlockWindowExclusive(commRank) ; ++ winNotify_->unlockWindow(commRank,0) ; + } + + void CService::createContext(void) +Index: src/manager/services_manager.cpp +=================================================================== +--- src/manager/services_manager.cpp (revision 2596) ++++ src/manager/services_manager.cpp (working copy) +@@ -30,10 +30,14 @@ + + MPI_Comm_rank(xiosComm_, &commRank) ; + winNotify_ = new CWindowManager(xiosComm_, maxBufferSize_,"CServicesManager::winNotify_") ; +- winNotify_->updateToExclusiveWindow(commRank, this, &CServicesManager::notificationsDumpOut) ; ++ winNotify_->lockWindow(commRank,0) ; ++ winNotify_->updateToWindow(commRank, this, &CServicesManager::notificationsDumpOut) ; ++ winNotify_->unlockWindow(commRank,0) ; + + winServices_ = new CWindowManager(xiosComm_, maxBufferSize_,"CServicesManager::winServices_") ; +- winServices_->updateToExclusiveWindow(commRank, this, &CServicesManager::servicesDumpOut) ; ++ winServices_->lockWindow(commRank,0) ; ++ winServices_->updateToWindow(commRank, this, &CServicesManager::servicesDumpOut) ; ++ winServices_->unlockWindow(commRank,0) ; + + MPI_Barrier(xiosComm_) ; + } +@@ -116,7 +120,9 @@ + + void CServicesManager::sendNotification(int rank) + { +- winNotify_->pushToExclusiveWindow(rank, this, &CServicesManager::notificationsDumpOut) ; ++ winNotify_->lockWindowExclusive(rank) ; ++ winNotify_->pushToLockedWindow(rank, this, &CServicesManager::notificationsDumpOut) ; ++ winNotify_->unlockWindow(rank) ; + } + + +@@ -140,7 +146,9 @@ + { + int commRank ; + MPI_Comm_rank(xiosComm_, &commRank) ; +- winNotify_->popFromExclusiveWindow(commRank, this, &CServicesManager::notificationsDumpIn) ; ++ winNotify_->lockWindowExclusive(commRank) ; ++ winNotify_->popFromLockedWindow(commRank, this, &CServicesManager::notificationsDumpIn) ; ++ winNotify_->unlockWindow(commRank) ; + if (notifyType_==NOTIFY_CREATE_SERVICE) createService() ; + else if (notifyType_==NOTIFY_CREATE_SERVICE_ONTO) createServiceOnto() ; + } +@@ -244,14 +252,16 @@ + winServices_->flushWindow(managerGlobalLeader_) ; + services_[std::tuple(poolId,serviceId,partitionId)]=std::make_tuple(type,size,nbPartitions,leader) ; + winServices_->updateToLockedWindow(managerGlobalLeader_, this, &CServicesManager::servicesDumpOut) ; +- winServices_->unlockWindowExclusive(managerGlobalLeader_) ; ++ winServices_->unlockWindow(managerGlobalLeader_) ; + + } + + bool CServicesManager::getServiceInfo(const std::string& poolId, const std::string& serviceId, const int& partitionId, int& type, + int& size, int& nbPartitions, int& leader, bool wait) + { +- winServices_->updateFromSharedWindow(managerGlobalLeader_, this, &CServicesManager::servicesDumpIn) ; ++ winServices_->lockWindowShared(managerGlobalLeader_) ; ++ winServices_->updateFromLockedWindow(managerGlobalLeader_, this, &CServicesManager::servicesDumpIn) ; ++ winServices_->unlockWindow(managerGlobalLeader_) ; + + if (wait) waitServiceRegistration(poolId, serviceId, partitionId) ; + auto it=services_.find(std::tuple(poolId,serviceId,partitionId)) ; +@@ -292,7 +302,9 @@ + + bool CServicesManager::hasService(const std::string& poolId, const std::string& serviceId, const int& partitionId) + { +- winServices_->updateFromSharedWindow(managerGlobalLeader_, this, &CServicesManager::servicesDumpIn) ; ++ winServices_->lockWindowShared(managerGlobalLeader_) ; ++ winServices_->updateFromLockedWindow(managerGlobalLeader_, this, &CServicesManager::servicesDumpIn) ; ++ winServices_->unlockWindow(managerGlobalLeader_) ; + auto it=services_.find(std::tuple(poolId, serviceId, partitionId)) ; + if ( it == services_.end()) return false ; + else return true ; +Index: src/manager/window_manager.cpp +=================================================================== +--- src/manager/window_manager.cpp (revision 2596) ++++ src/manager/window_manager.cpp (working copy) +@@ -6,11 +6,11 @@ + namespace xios + { + +- const MPI_Aint CWindowManager::OFFSET_LOCK ; +- const int CWindowManager::SIZE_LOCK ; +- const MPI_Aint CWindowManager::OFFSET_BUFFER_SIZE ; +- const int CWindowManager::SIZE_BUFFER_SIZE ; +- const MPI_Aint CWindowManager::OFFSET_BUFFER; +- const int CWindowManager::WINDOWS_LOCKED ; ++// const MPI_Aint CWindowManager::OFFSET_LOCK ; ++// const int CWindowManager::SIZE_LOCK ; ++// const MPI_Aint CWindowManager::OFFSET_BUFFER_SIZE ; ++// const int CWindowManager::SIZE_BUFFER_SIZE ; ++// const MPI_Aint CWindowManager::OFFSET_BUFFER; ++// const int CWindowManager::WINDOWS_LOCKED ; + } + +Index: src/manager/window_manager.hpp +=================================================================== +--- src/manager/window_manager.hpp (revision 2596) ++++ src/manager/window_manager.hpp (working copy) +@@ -1,300 +1,376 @@ +-#ifndef __WINDOW_MANAGER_HPP__ +-#define __WINDOW_MANAGER_HPP__ +- +-#include +-#include "mpi.hpp" +-#include "buffer_in.hpp" +-#include "buffer_out.hpp" +-#include "message.hpp" +-#include "window_base.hpp" +- +-namespace xios +-{ +- +- +- class CWindowManager : public CWindowBase +- { +- +- private : +- static const MPI_Aint OFFSET_LOCK=0 ; +- static const int SIZE_LOCK=sizeof(int) ; +- static const MPI_Aint OFFSET_BUFFER_SIZE=OFFSET_LOCK+SIZE_LOCK ; +- static const int SIZE_BUFFER_SIZE=sizeof(size_t) ; +- static const MPI_Aint OFFSET_BUFFER=OFFSET_BUFFER_SIZE+SIZE_BUFFER_SIZE ; +- static const int WINDOWS_LOCKED=-1 ; +- +- MPI_Win window_ ; +- void * winBuffer_ ; +- map lastTimeLock_ ; +- const double latency_=0e-2 ; +- +- public : +- +- CWindowManager(MPI_Comm winComm, size_t bufferSize, const string name) : CWindowBase(winComm, bufferSize + OFFSET_BUFFER_SIZE, name) +- { +- int lock=0 ; +- size_t size=0 ; +- int commRank ; +- MPI_Comm_rank(winComm, &commRank) ; +- lockExclusive(commRank) ; +- put(&lock, SIZE_LOCK, MPI_CHAR, commRank, OFFSET_LOCK, SIZE_LOCK, MPI_CHAR) ; +- put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, commRank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR) ; +- unlockExclusive(commRank) ; +- MPI_Barrier(winComm) ; +- } +- +- void lockWindow(int rank, int state ) +- { +- int lock=state ; +- double time ; +- auto it=lastTimeLock_.find(rank) ; +- if (it == lastTimeLock_.end()) +- { +- lastTimeLock_[rank] = 0. ; +- it=lastTimeLock_.find(rank) ; +- } +- double& lastTime = it->second ; +- +- do +- { +- time=MPI_Wtime() ; +- while(time-lastTime < latency_) time=MPI_Wtime() ; +- int flag ; +- MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, MPI_STATUS_IGNORE); +- compareAndSwap(&WINDOWS_LOCKED, &state, &lock, MPI_INT, rank, OFFSET_LOCK) ; +- flush(rank) ; +- lastTime=MPI_Wtime() ; +- } while (lock!=state) ; +- +- +- } +- +- void lockWindowExclusive(int rank, int state ) +- { +- int lock=state ; +- double time ; +- auto it=lastTimeLock_.find(rank) ; +- if (it == lastTimeLock_.end()) +- { +- lastTimeLock_[rank] = 0. ; +- it=lastTimeLock_.find(rank) ; +- } +- double& lastTime = it->second ; +- +- do +- { +- time=MPI_Wtime() ; +- while(time-lastTime < latency_) time=MPI_Wtime() ; +- int flag ; +- MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, MPI_STATUS_IGNORE); +- lockExclusive(rank) ; +- compareAndSwap(&WINDOWS_LOCKED, &state, &lock, MPI_INT, rank, OFFSET_LOCK) ; +- unlockExclusive(rank) ; +- lastTime=MPI_Wtime() ; +- } while (lock!=state) ; +- } +- +- void lockWindowExclusive(int rank) +- { +- lockExclusive(rank) ; +- } +- +- void lockWindowShared(int rank) +- { +- lockShared(rank) ; +- } +- +- void unlockWindowExclusive(int rank) +- { +- unlockExclusive(rank) ; +- } +- +- void unlockWindowShared(int rank) +- { +- unlockShared(rank) ; +- } +- +- void lockWindow(int rank) +- { +- lockWindowExclusive(rank) ; +- } +- +- void unlockWindow(int rank) +- { +- unlockWindowExclusive(rank) ; +- } +- +- void flushWindow(int rank) +- { +- flush(rank) ; +- } +- +- void unlockWindow(int rank, int state ) +- { +- int lock ; +- compareAndSwap(&state, &WINDOWS_LOCKED, &lock, MPI_INT, rank, OFFSET_LOCK) ; +- flush(rank) ; +- } +- +- template< class T > +- void updateToWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) +- { +- updateToExclusiveWindow(rank, object, dumpOut) ; +- } +- +- template< class T > +- void updateToExclusiveWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) +- { +- lockExclusive(rank) ; +- updateToLockedWindow(rank, object, dumpOut) ; +- unlockExclusive(rank) ; +- } +- +- template< class T > +- void updateTosharedWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) +- { +- lockShared(rank) ; +- updateToLockedWindow(rank, object, dumpOut) ; +- unlockShared(rank) ; +- } +- +- template< class T > +- void updateToLockedWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) +- { +- CBufferOut buffer ; +- (object->*dumpOut)(buffer) ; +- size_t size=buffer.count() ; +- +- put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR) ; +- put(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR) ; +- flush(rank) ; +- } +- +- template< typename T > +- void updateFromWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) +- { +- updateFromExclusiveWindow(rank,object, dumpIn) ; +- } +- +- template< typename T > +- void updateFromExclusiveWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) +- { +- size_t size ; +- lockExclusive(rank) ; +- updateFromLockedWindow(rank,object, dumpIn) ; +- unlockExclusive(rank) ; +- } +- +- template< typename T > +- void updateFromSharedWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) +- { +- size_t size ; +- lockShared(rank) ; +- updateFromLockedWindow(rank,object, dumpIn) ; +- unlockShared(rank) ; +- } +- +- template< typename T > +- void updateFromLockedWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) +- { +- size_t size ; +- +- get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR) ; +- flush(rank) ; +- CBufferIn buffer(size) ; +- get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR) ; +- flush(rank) ; +- +- (object->*dumpIn)(buffer) ; +- } +- +- +- +- template< class T > +- void pushToWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) +- { +- pushToExclusiveWindow(rank, object, dumpOut) ; +- } +- +- template< class T > +- void pushToExclusiveWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) +- { +- lockExclusive(rank) ; +- pushToLockedWindow(rank, object, dumpOut) ; +- unlockExclusive(rank) ; +- } +- +- template< class T > +- void pushToSharedWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) +- { +- lockShared(rank) ; +- pushToLockedWindow(rank, object, dumpOut) ; +- unlockShared(rank) ; +- } +- +- template< class T > +- void pushToLockedWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) +- { +- size_t size ; +- get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR) ; +- flush(rank) ; +- CBufferOut buffer ; +- (object->*dumpOut)(buffer) ; +- size_t bufferSize=buffer.count() ; +- size_t newSize = size + bufferSize; +- put(&newSize, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR) ; +- put(buffer.start(), bufferSize, MPI_CHAR, rank, OFFSET_BUFFER+size, bufferSize, MPI_CHAR) ; +- flush(rank) ; +- } +- +- +- +- template< typename T > +- void popFromWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) +- { +- popFromExclusiveWindow(rank,object, dumpIn) ; +- } +- +- template< typename T > +- void popFromExclusiveWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) +- { +- lockExclusive(rank) ; +- popFromLockedWindow(rank,object, dumpIn) ; +- unlockExclusive(rank) ; +- +- } +- +- template< typename T > +- void popFromSharedWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) +- { +- lockShared(rank) ; +- popFromLockedWindow(rank,object, dumpIn) ; +- unlockShared(rank) ; +- } +- +- template< typename T > +- void popFromLockedWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) +- { +- size_t size ; +- get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR) ; +- flush(rank) ; +- CBufferIn buffer(size) ; +- get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR) ; +- flush(rank) ; +- (object->*dumpIn)(buffer) ; +- +- size=buffer.remain() ; +- put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR) ; +- put(buffer.ptr(),buffer.remain(), MPI_CHAR, rank, OFFSET_BUFFER, buffer.remain(), MPI_CHAR) ; +- flush(rank) ; +- } +- +- ~CWindowManager() +- { +- } +- } ; +-} +- +- +- +-#endif +\ No newline at end of file ++#ifndef __WINDOW_MANAGER_HPP__ ++#define __WINDOW_MANAGER_HPP__ ++ ++#include ++#include "mpi.hpp" ++#include "buffer_in.hpp" ++#include "buffer_out.hpp" ++#include "message.hpp" ++ ++namespace xios ++{ ++ ++ ++ class CWindowManager ++ { ++ ++ private : ++ const MPI_Aint OFFSET_LOCK=0 ; ++ const int SIZE_LOCK=sizeof(int) ; ++ const MPI_Aint OFFSET_BUFFER_SIZE=OFFSET_LOCK+SIZE_LOCK ; ++ const int SIZE_BUFFER_SIZE=sizeof(size_t) ; ++ const MPI_Aint OFFSET_BUFFER=OFFSET_BUFFER_SIZE+SIZE_BUFFER_SIZE ; ++ const int WINDOWS_LOCKED=-1 ; ++ ++ MPI_Win window_ ; ++ void * winBuffer_ ; ++ map lastTimeLock_ ; ++ const double latency_=0e-2 ; ++ ++ public : ++ ++ CWindowManager(MPI_Comm winComm, size_t bufferSize, const string name) ++ { ++ const MPI_Aint windowSize=bufferSize+OFFSET_BUFFER ; ++ MPI_Win_allocate(windowSize, 1, MPI_INFO_NULL, winComm, &winBuffer_, &window_) ; ++ int lock=0 ; ++ size_t size=0 ; ++ int commRank ; ++ MPI_Comm_rank(winComm, &commRank) ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, commRank, 0, window_) ; ++ MPI_Put(&lock, SIZE_LOCK, MPI_CHAR, commRank, OFFSET_LOCK, SIZE_LOCK, MPI_CHAR, window_) ; ++ MPI_Put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, commRank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_unlock(commRank, window_) ; ++ MPI_Barrier(winComm) ; ++ } ++ ++ void lockWindow(int rank, int state ) ++ { ++ int lock=state ; ++ double time ; ++ auto it=lastTimeLock_.find(rank) ; ++ if (it == lastTimeLock_.end()) ++ { ++ lastTimeLock_[rank] = 0. ; ++ it=lastTimeLock_.find(rank) ; ++ } ++ double& lastTime = it->second ; ++ ++ do ++ { ++ time=MPI_Wtime() ; ++ while(time-lastTime < latency_) time=MPI_Wtime() ; ++ int flag ; ++ MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, MPI_STATUS_IGNORE); ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Compare_and_swap(&WINDOWS_LOCKED, &state, &lock, MPI_INT, rank, OFFSET_LOCK, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ lastTime=MPI_Wtime() ; ++ } while (lock!=state) ; ++ ++ ++ } ++ ++ void lockWindowExclusive(int rank, int state ) ++ { ++ int lock=state ; ++ double time ; ++ auto it=lastTimeLock_.find(rank) ; ++ if (it == lastTimeLock_.end()) ++ { ++ lastTimeLock_[rank] = 0. ; ++ it=lastTimeLock_.find(rank) ; ++ } ++ double& lastTime = it->second ; ++ ++ do ++ { ++ time=MPI_Wtime() ; ++ while(time-lastTime < latency_) time=MPI_Wtime() ; ++ int flag ; ++ MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, MPI_STATUS_IGNORE); ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Compare_and_swap(&WINDOWS_LOCKED, &state, &lock, MPI_INT, rank, OFFSET_LOCK, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ lastTime=MPI_Wtime() ; ++ } while (lock!=state) ; ++ } ++ ++ void lockWindowExclusive(int rank) ++ { ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ } ++ ++ void lockWindowShared(int rank) ++ { ++ MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, window_) ; ++ } ++ ++ void unlockWindow(int rank) ++ { ++ MPI_Win_unlock(rank, window_) ; ++ } ++ ++ void flushWindow(int rank) ++ { ++ MPI_Win_flush(rank, window_) ; ++ } ++ ++ void unlockWindow(int rank, int state ) ++ { ++ int lock ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Compare_and_swap(&state, &WINDOWS_LOCKED, &lock, MPI_INT, rank, OFFSET_LOCK, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ } ++ ++ template< class T > ++ void updateToWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) ++ { ++ CBufferOut buffer ; ++ (object->*dumpOut)(buffer) ; ++ size_t size=buffer.count() ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ } ++ ++ template< class T > ++ void updateToExclusiveWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) ++ { ++ CBufferOut buffer ; ++ (object->*dumpOut)(buffer) ; ++ size_t size=buffer.count() ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ } ++ ++ template< class T > ++ void updateTosharedWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) ++ { ++ CBufferOut buffer ; ++ (object->*dumpOut)(buffer) ; ++ size_t size=buffer.count() ; ++ MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, window_) ; ++ MPI_Put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ } ++ ++ template< class T > ++ void updateToLockedWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) ++ { ++ CBufferOut buffer ; ++ (object->*dumpOut)(buffer) ; ++ size_t size=buffer.count() ; ++// MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank, window_) ; ++// MPI_Win_unlock(rank, window_) ; ++ } ++ ++ template< typename T > ++ void updateFromWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) ++ { ++ size_t size ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferIn buffer(size) ; ++ MPI_Get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ (object->*dumpIn)(buffer) ; ++ } ++ ++ template< typename T > ++ void updateFromExclusiveWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) ++ { ++ size_t size ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferIn buffer(size) ; ++ MPI_Get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ (object->*dumpIn)(buffer) ; ++ } ++ ++ template< typename T > ++ void updateFromSharedWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) ++ { ++ size_t size ; ++ MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferIn buffer(size) ; ++ MPI_Get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ (object->*dumpIn)(buffer) ; ++ } ++ ++ template< typename T > ++ void updateFromLockedWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) ++ { ++ size_t size ; ++// MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferIn buffer(size) ; ++ MPI_Get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++// MPI_Win_unlock(rank, window_) ; ++ MPI_Win_flush(rank, window_) ; ++ (object->*dumpIn)(buffer) ; ++ } ++ ++ ++ template< class T > ++ void pushToWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) ++ { ++ size_t size ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferOut buffer ; ++ (object->*dumpOut)(buffer) ; ++ size_t bufferSize=buffer.count() ; ++ size_t newSize = size + bufferSize; ++ MPI_Put(&newSize, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.start(), bufferSize, MPI_CHAR, rank, OFFSET_BUFFER+size, bufferSize, MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ } ++ ++ template< class T > ++ void pushToExclusiveWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) ++ { ++ size_t size ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferOut buffer ; ++ (object->*dumpOut)(buffer) ; ++ size_t bufferSize=buffer.count() ; ++ size_t newSize = size + bufferSize; ++ MPI_Put(&newSize, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.start(), bufferSize, MPI_CHAR, rank, OFFSET_BUFFER+size, bufferSize, MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ } ++ ++ template< class T > ++ void pushToSharedWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) ++ { ++ size_t size ; ++ MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferOut buffer ; ++ (object->*dumpOut)(buffer) ; ++ size_t bufferSize=buffer.count() ; ++ size_t newSize = size + bufferSize; ++ MPI_Put(&newSize, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.start(), bufferSize, MPI_CHAR, rank, OFFSET_BUFFER+size, bufferSize, MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ } ++ ++ template< class T > ++ void pushToLockedWindow(int rank, T* object, void (T::*dumpOut)(CBufferOut&) ) ++ { ++ size_t size ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferOut buffer ; ++ (object->*dumpOut)(buffer) ; ++ size_t bufferSize=buffer.count() ; ++ size_t newSize = size + bufferSize; ++ MPI_Put(&newSize, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.start(), bufferSize, MPI_CHAR, rank, OFFSET_BUFFER+size, bufferSize, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank, window_) ; ++ } ++ ++ template< typename T > ++ void popFromWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) ++ { ++ size_t size ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferIn buffer(size) ; ++ MPI_Get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ (object->*dumpIn)(buffer) ; ++ ++ size=buffer.remain() ; ++ MPI_Put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.ptr(),buffer.remain(), MPI_CHAR, rank, OFFSET_BUFFER, buffer.remain(), MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ ++ } ++ ++ template< typename T > ++ void popFromExclusiveWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) ++ { ++ size_t size ; ++ MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferIn buffer(size) ; ++ MPI_Get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ (object->*dumpIn)(buffer) ; ++ ++ size=buffer.remain() ; ++ MPI_Put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.ptr(),buffer.remain(), MPI_CHAR, rank, OFFSET_BUFFER, buffer.remain(), MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ ++ } ++ ++ template< typename T > ++ void popFromSharedWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) ++ { ++ size_t size ; ++ MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, window_) ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferIn buffer(size) ; ++ MPI_Get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ (object->*dumpIn)(buffer) ; ++ ++ size=buffer.remain() ; ++ MPI_Put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.ptr(),buffer.remain(), MPI_CHAR, rank, OFFSET_BUFFER, buffer.remain(), MPI_CHAR, window_) ; ++ MPI_Win_unlock(rank, window_) ; ++ ++ } ++ ++ template< typename T > ++ void popFromLockedWindow(int rank, T* object, void (T::*dumpIn)(CBufferIn&) ) ++ { ++ size_t size ; ++ MPI_Get(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ CBufferIn buffer(size) ; ++ MPI_Get(buffer.start(), size, MPI_CHAR, rank,OFFSET_BUFFER, size, MPI_CHAR, window_) ; ++ MPI_Win_flush(rank,window_) ; ++ (object->*dumpIn)(buffer) ; ++ ++ size=buffer.remain() ; ++ MPI_Put(&size, SIZE_BUFFER_SIZE, MPI_CHAR, rank, OFFSET_BUFFER_SIZE, SIZE_BUFFER_SIZE, MPI_CHAR, window_) ; ++ MPI_Put(buffer.ptr(),buffer.remain(), MPI_CHAR, rank, OFFSET_BUFFER, buffer.remain(), MPI_CHAR, window_) ; ++ MPI_Win_flush(rank, window_) ; ++ } ++ ++ ~CWindowManager() ++ { ++ MPI_Win_free(&window_) ; ++ } ++ } ; ++} ++ ++ ++ ++#endif diff --git a/xios_examples/__init__.py b/xios_examples/__init__.py new file mode 100644 index 0000000..df083e3 --- /dev/null +++ b/xios_examples/__init__.py @@ -0,0 +1,3 @@ +""" +Enable this folder to be a module path, for imports and test discovery. +""" diff --git a/xios_examples/read_axis_resample/Makefile b/xios_examples/read_axis_resample/Makefile new file mode 100644 index 0000000..dc913c2 --- /dev/null +++ b/xios_examples/read_axis_resample/Makefile @@ -0,0 +1,58 @@ +# Make file for the resample demonstartion XIOS programme +# Targets provided our detailed below... +# +# all: (default) Build the resample programme +# clean: Delete all final products and working files +# run: run the programme +# +# Environment Variables expected by this MakeFile: +# +# NETCDF_LIB_DIR: the directories for the netCDF lib files +# encoded as a -L string, e.g. +# "-L/dir1 -L/dir2" +# NETCDF_INC_DIR: the directories for the netCDF include files +# encoded as a -I string, e.g. +# "-I/dir3 -I/dir4" +# (note, this is for consistency with the XIOS build process +# required for the CI build machine. +# this is not required for other directories) +# +# XIOS_INCDIR: The directory for XIOS include files +# XIOS_LIBDIR: The directory for XIOS lib files +# XIOS_BINDIR: The directory for XIOS binary files + +FCFLAGS = -g -ffree-line-length-none + +FC = mpif90 # compiler driver for MPI programs + +# compiler flag, includes +FCFLAGS += -I$(XIOS_INCDIR) $(NETCDF_INCDIR) + +# loader flags +LDFLAGS = \ + -L$(XIOS_LIBDIR) \ + $(NETCDF_LIBDIR) \ + -lxios \ + -lnetcdf \ + -lnetcdff \ + -lstdc++ + +.PHONY: all, clean, run + +all: resample + +# fortran compilation +%.o: %.F90 + $(FC) $(FCFLAGS) -c $< + +# fortran linking +resample: resample.o + $(FC) -o resample.exe resample.o $(LDFLAGS) \ + && ln -fs $(XIOS_BINDIR)/xios_server.exe . + +run: + mpiexec -n 1 ./resample.exe : -n 1 ./xios_server.exe + +# cleanup +clean: + rm -f *.exe *.o *.mod *.MOD *.out *.err *.nc diff --git a/xios_examples/read_axis_resample/__init__.py b/xios_examples/read_axis_resample/__init__.py new file mode 100644 index 0000000..df083e3 --- /dev/null +++ b/xios_examples/read_axis_resample/__init__.py @@ -0,0 +1,3 @@ +""" +Enable this folder to be a module path, for imports and test discovery. +""" diff --git a/xios_examples/read_axis_resample/axis_input_edge_simple_square_ten.cdl b/xios_examples/read_axis_resample/axis_input_edge_simple_square_ten.cdl new file mode 100644 index 0000000..cdddf4e --- /dev/null +++ b/xios_examples/read_axis_resample/axis_input_edge_simple_square_ten.cdl @@ -0,0 +1,32 @@ +netcdf axis_input { +dimensions: + z = 10 ; + z_resample = 5 ; +variables: + float z(z) ; + z:long_name = "original z coordinate" ; + z:units = "1"; + float z_resample(z_resample) ; + z_resample:long_name = "resampled z coordinate" ; + z_resample:units = "1"; + double original_data(z) ; + original_data:long_name = "input data values" ; + original_data:units = "1"; + double resample_data(z_resample) ; + resample_data:long_name = "expected resampled data values" ; + resample_data:units = "1"; + +// global attributes: + :title = "Input data for XIOS Axis resampling; data is a square function of the z coordinate." ; + +data: + + z = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ; + + z_resample = 1.5, 3.5, 5.5, 7.5, 9.5 ; + + original_data = 1, 4, 9, 16, 25, 36, 49, 64, 81, 100 ; + + resample_data = 2.25, 12.25, 30.25, 56.25, 90.25 ; + +} diff --git a/xios_examples/read_axis_resample/axis_input_simple_square_ten.cdl b/xios_examples/read_axis_resample/axis_input_simple_square_ten.cdl new file mode 100644 index 0000000..8ba3391 --- /dev/null +++ b/xios_examples/read_axis_resample/axis_input_simple_square_ten.cdl @@ -0,0 +1,32 @@ +netcdf axis_input { +dimensions: + z = 10 ; + z_resample = 4 ; +variables: + float z(z) ; + z:long_name = "original z coordinate" ; + z:units = "1"; + float z_resample(z_resample) ; + z_resample:long_name = "resampled z coordinate" ; + z_resample:units = "1"; + double original_data(z) ; + original_data:long_name = "input data values" ; + original_data:units = "1"; + double resample_data(z_resample) ; + resample_data:long_name = "expected resampled data values" ; + resample_data:units = "1"; + +// global attributes: + :title = "Input data for XIOS Axis resampling; data is a square function of the z coordinate." ; + +data: + + z = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ; + + z_resample = 1.5, 3.5, 5.5, 7.5 ; + + original_data = 1, 4, 9, 16, 25, 36, 49, 64, 81, 100 ; + + resample_data = 2.25, 12.25, 30.25, 56.25 ; + +} diff --git a/xios_examples/read_axis_resample/iodef.xml b/xios_examples/read_axis_resample/iodef.xml new file mode 100644 index 0000000..c57fc1d --- /dev/null +++ b/xios_examples/read_axis_resample/iodef.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/xios_examples/read_axis_resample/main.xml b/xios_examples/read_axis_resample/main.xml new file mode 100644 index 0000000..8699177 --- /dev/null +++ b/xios_examples/read_axis_resample/main.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + rdata-edata + + + + + + + + + + + + + + + + + + diff --git a/xios_examples/read_axis_resample/resample.F90 b/xios_examples/read_axis_resample/resample.F90 new file mode 100644 index 0000000..2cccced --- /dev/null +++ b/xios_examples/read_axis_resample/resample.F90 @@ -0,0 +1,102 @@ +!----------------------------------------------------------------------------- +! (C) Crown copyright 2020 Met Office. All rights reserved. +! The file LICENCE, distributed with this code, contains details of the terms +! under which the code may be used. +!----------------------------------------------------------------------------- +!> Resample on a 1D Axis using the axis_input.nc file +!> +program resample + use xios + use mpi + + implicit none + + integer :: comm = -1 + integer :: rank = -1 + integer :: npar = 0 + + call initialise() + call simulate() + call finalise() +contains + + subroutine initialise() + + type(xios_date) :: origin + type(xios_date) :: start + type(xios_duration) :: tstep + integer :: mpi_error + + ! Arbitrary datetime setup, required for XIOS but unused + origin = xios_date(2022, 2, 2, 12, 0, 0) + start = xios_date(2022, 12, 13, 12, 0, 0) + tstep = xios_hour + + ! Initialise MPI and XIOS + call MPI_INIT(mpi_error) + + call xios_initialize('client', return_comm=comm) + + call MPI_Comm_rank(comm, rank, mpi_error) + call MPI_Comm_size(comm, npar, mpi_error) + + call xios_context_initialize('main', comm) + call xios_set_time_origin(origin) + call xios_set_start_date(start) + call xios_set_timestep(tstep) + + call xios_close_context_definition() + + end subroutine initialise + + subroutine finalise() + + integer :: mpi_error + + ! Finalise XIOS and MPI + call xios_context_finalize() + call MPI_Comm_free(comm, mpi_error) + call xios_finalize() + call MPI_Finalize(mpi_error) + + end subroutine finalise + + subroutine simulate() + + type(xios_date) :: current + integer :: ts + integer :: lenz + integer :: lenrz + + ! Allocatable arrays, size is taken from input file + double precision, dimension (:), allocatable :: inodata + double precision, dimension (:), allocatable :: inedata + + call xios_get_axis_attr('z', n_glo=lenz) + call xios_get_axis_attr('z_resample', n_glo=lenrz) + + allocate ( inodata(lenz) ) + allocate ( inedata(lenrz) ) + + ! Load data from the input file + call xios_recv_field('odataz', inodata) + call xios_recv_field('edataz', inedata) + + do ts=1, 1 + call xios_update_calendar(ts) + call xios_get_current_date(current) + ! Send (copy) the original data to the output file. + ! The interpolate_axis and field-ref in main.xml will + ! also write the interpolated data into the output file. + call xios_send_field('odata', inodata) + ! Send (copy) the expected data to the output file. + ! The diff field in main.xml will also output a diff variable. + call xios_send_field('edata', inedata) + enddo + + deallocate (inodata) + deallocate (inedata) + + end subroutine simulate + +end program resample diff --git a/xios_examples/read_axis_resample/test_resample_cases.py b/xios_examples/read_axis_resample/test_resample_cases.py new file mode 100644 index 0000000..93e92b2 --- /dev/null +++ b/xios_examples/read_axis_resample/test_resample_cases.py @@ -0,0 +1,114 @@ +import copy +import glob +import netCDF4 +import numpy as np +import os +import subprocess +import glob +import unittest + +this_path = os.path.realpath(__file__) +this_dir = os.path.dirname(this_path) + +class TestResample(unittest.TestCase): + """ + UnitTest class to contain tests, + 1 test case function per input `.cdl` file + + """ + @classmethod + def setUpClass(cls): + """ + First, build the fortran code only once for this class. + + """ + subprocess.run(['make', 'clean'], cwd=this_dir, check=True) + subprocess.run(['make'], cwd=this_dir, check=True) + if os.environ.get('MVER', '') == 'XIOS3/trunk': + with open(os.path.join(this_dir, 'iodef.xml'), 'r') as ioin: + iodef_in = ioin.read() + # patch in transport protocol choice for XIOS3 + # needed for CI runners + in2 = '' + in3 = ('\n' + ' p2p') + iodef_out = iodef_in.replace(in2, in3) + with open(os.path.join(this_dir, 'iodef.xml'), 'w') as ioout: + ioout.write(iodef_out) + + def tearDown(self): + """ + After each test function, + report any errors from XIOS, then + remove the input and output netCDF files. + + """ + + for ef in glob.glob('{}/*.err'.format(this_dir)): + print(ef) + with open(ef, 'r') as efile: + print(efile.read(), flush=True) + + os.remove('{}/axis_input.nc'.format(this_dir)) + os.remove('{}/axis_output.nc'.format(this_dir)) + + @classmethod + def tearDownClass(cls): + """ + Finally, clean the build for this class, after all tests have run. + + """ + subprocess.run(['make', 'clean'], cwd=this_dir) + +# A list of input `.cdl` files where XIOS is known to produce different +# output from the expected output data +# for future investigation / ToDo +known_failures = ['test_axis_input_edge_simple_square_ten.cdl'] + +# iterate through `.cdl` files in this test case folder +for f in glob.glob('{}/*.cdl'.format(this_dir)): + def make_a_test(inf): + """ + this function makes a test case and returns it as a function. + + """ + # always copy for value, don't pass by reference. + infile = copy.copy(inf) + # expected by the fortran XIOS resample program's main.xml + outfile = 'axis_input.nc' + def test_resample(self): + # create a netCDF file from the `.cdl` input + subprocess.run(['ncgen', '-k', 'nc4', '-o', 'axis_input.nc', + infile], cwd=this_dir, check=True) + # run the compiled Fortran XIOS programme + subprocess.run(['mpiexec', '-n', '1', './resample.exe', ':', + '-n', '1', './xios_server.exe'], + cwd=this_dir, check=True) + # load the result netCDF file + rootgrp = netCDF4.Dataset('{}/axis_output.nc'.format(this_dir), + 'r') + # read data from the resampled, expected & diff variables + diff = rootgrp['resampled_minus_resample'][:] + # prepare message for failure + msg = ('the expected resample data array\n {exp}\n ' + 'differs from the resampled data array\n {res} \n ' + 'with diff \n {diff}\n') + msg = msg.format(exp=rootgrp['resample_data'][:], + res=rootgrp['resampled_data'][:], + diff=diff) + if np.any(diff): + # print message for fail case, + # as expected failures do not report msg. + print(msg) + # assert that all of the `diff` varaible values are zero + self.assertTrue(not np.any(diff), msg=msg) + return test_resample + # unique name for the test + tname = 'test_{}'.format(os.path.basename(f)) + # add the test as an attribute (function) to the test class + if tname in known_failures: + # set decorator @unittest.expectedFailure + setattr(TestResample, tname, unittest.expectedFailure(make_a_test(f))) + else: + setattr(TestResample, tname, make_a_test(f)) diff --git a/xios_examples/read_axis_resample/xios.xml b/xios_examples/read_axis_resample/xios.xml new file mode 100644 index 0000000..9ec1df0 --- /dev/null +++ b/xios_examples/read_axis_resample/xios.xml @@ -0,0 +1,22 @@ + + + + + performance + + + 1.0 + + + + + true + + 100 + + + true + + + +