From de08957031354c9914b1d48b6ef950f73b13a830 Mon Sep 17 00:00:00 2001 From: marqh Date: Tue, 13 Feb 2024 11:43:02 +0000 Subject: [PATCH 1/6] test multiple XIOS versions --- .github/workflows/buildTest.yml | 20 +- patches/xios3/revert_svn2517_transport.patch | 1243 ++++++++++++++++++ 2 files changed, 1256 insertions(+), 7 deletions(-) create mode 100644 patches/xios3/revert_svn2517_transport.patch diff --git a/.github/workflows/buildTest.yml b/.github/workflows/buildTest.yml index cd51250..9c47918 100644 --- a/.github/workflows/buildTest.yml +++ b/.github/workflows/buildTest.yml @@ -6,6 +6,9 @@ jobs: build_test: name: build XIOS and run tests runs-on: ubuntu-latest + strategy: + matrix: + version: [XIOS/trunk@2252, XIOS2/trunk, XIOS3/trunk] steps: # Check out repository branch - uses: actions/checkout@v4 @@ -16,17 +19,20 @@ 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 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 From e0700e0fa580cd5fa681a292d48e911a52d2f933 Mon Sep 17 00:00:00 2001 From: marqh Date: Wed, 24 Jan 2024 12:14:37 +0000 Subject: [PATCH 2/6] resample usage example --- .github/workflows/buildTest.yml | 16 +++ README.md | 10 ++ xios_examples/read_axis_resample/Makefile | 38 +++++++ .../read_axis_resample/axis_input.cdl | 32 ++++++ xios_examples/read_axis_resample/iodef.xml | 7 ++ xios_examples/read_axis_resample/main.xml | 34 ++++++ xios_examples/read_axis_resample/resample.F90 | 102 ++++++++++++++++++ xios_examples/read_axis_resample/xios.xml | 22 ++++ 8 files changed, 261 insertions(+) create mode 100644 xios_examples/read_axis_resample/Makefile create mode 100644 xios_examples/read_axis_resample/axis_input.cdl create mode 100644 xios_examples/read_axis_resample/iodef.xml create mode 100644 xios_examples/read_axis_resample/main.xml create mode 100644 xios_examples/read_axis_resample/resample.F90 create mode 100644 xios_examples/read_axis_resample/xios.xml diff --git a/.github/workflows/buildTest.yml b/.github/workflows/buildTest.yml index 9c47918..a007e1d 100644 --- a/.github/workflows/buildTest.yml +++ b/.github/workflows/buildTest.yml @@ -38,3 +38,19 @@ jobs: 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/XIOS2/bin + ls -l $XIOS_BINDIR + export XIOS_INCDIR=$PWD/XIOS2/inc + ls -l $XIOS_INCDIR + export XIOS_LIBDIR=$PWD/XIOS2/lib + ls -l $XIOS_BINDIR + + cd xios_examples/read_axis_resample + make + make run + ncdump axis_output.nc + cd ../.. 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/xios_examples/read_axis_resample/Makefile b/xios_examples/read_axis_resample/Makefile new file mode 100644 index 0000000..3b7fa62 --- /dev/null +++ b/xios_examples/read_axis_resample/Makefile @@ -0,0 +1,38 @@ +FCFLAGS = -g -ffree-line-length-none +NETCDF_LIB_DIR64 = $(NETCDF_DIR)/lib64 + +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++ + +all: nc 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 . + +nc: + ncgen -k nc4 -o axis_input.nc axis_input.cdl + +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/axis_input.cdl b/xios_examples/read_axis_resample/axis_input.cdl new file mode 100644 index 0000000..8ba3391 --- /dev/null +++ b/xios_examples/read_axis_resample/axis_input.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/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 + + + + From 4036d8a75cf82103a6d4fb2f4771b053af579669 Mon Sep 17 00:00:00 2001 From: marqh Date: Wed, 24 Jan 2024 17:00:00 +0000 Subject: [PATCH 3/6] add python for test case scripting --- .github/workflows/buildTest.yml | 9 +- dependencies | 2 + xios_examples/__init__.py | 3 + xios_examples/read_axis_resample/Makefile | 30 ++++-- xios_examples/read_axis_resample/__init__.py | 3 + .../axis_input_edge_simple_square_ten.cdl | 32 +++++++ ...t.cdl => axis_input_simple_square_ten.cdl} | 0 .../read_axis_resample/test_resample_cases.py | 92 +++++++++++++++++++ 8 files changed, 157 insertions(+), 14 deletions(-) create mode 100644 xios_examples/__init__.py create mode 100644 xios_examples/read_axis_resample/__init__.py create mode 100644 xios_examples/read_axis_resample/axis_input_edge_simple_square_ten.cdl rename xios_examples/read_axis_resample/{axis_input.cdl => axis_input_simple_square_ten.cdl} (100%) create mode 100644 xios_examples/read_axis_resample/test_resample_cases.py diff --git a/.github/workflows/buildTest.yml b/.github/workflows/buildTest.yml index a007e1d..72c407d 100644 --- a/.github/workflows/buildTest.yml +++ b/.github/workflows/buildTest.yml @@ -43,14 +43,7 @@ jobs: . arch/arch-GCC_LINUX_APT.env . arch/arch-GCC_LINUX_APT.path export XIOS_BINDIR=$PWD/XIOS2/bin - ls -l $XIOS_BINDIR export XIOS_INCDIR=$PWD/XIOS2/inc - ls -l $XIOS_INCDIR export XIOS_LIBDIR=$PWD/XIOS2/lib - ls -l $XIOS_BINDIR - cd xios_examples/read_axis_resample - make - make run - ncdump axis_output.nc - cd ../.. + python3 -m unittest Discover -v -s xios_examples 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/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 index 3b7fa62..0824ec0 100644 --- a/xios_examples/read_axis_resample/Makefile +++ b/xios_examples/read_axis_resample/Makefile @@ -1,9 +1,30 @@ +# 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 -NETCDF_LIB_DIR64 = $(NETCDF_DIR)/lib64 FC = mpif90 # compiler driver for MPI programs - # compiler flag, includes FCFLAGS += -I$(XIOS_INCDIR) $(NETCDF_INCDIR) @@ -16,7 +37,7 @@ LDFLAGS = \ -lnetcdff \ -lstdc++ -all: nc resample +all: resample # fortran compilation %.o: %.F90 @@ -27,9 +48,6 @@ resample: resample.o $(FC) -o resample.exe resample.o $(LDFLAGS) \ && ln -fs $(XIOS_BINDIR)/xios_server.exe . -nc: - ncgen -k nc4 -o axis_input.nc axis_input.cdl - run: mpiexec -n 1 ./resample.exe : -n 1 ./xios_server.exe 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.cdl b/xios_examples/read_axis_resample/axis_input_simple_square_ten.cdl similarity index 100% rename from xios_examples/read_axis_resample/axis_input.cdl rename to xios_examples/read_axis_resample/axis_input_simple_square_ten.cdl 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..5be2f56 --- /dev/null +++ b/xios_examples/read_axis_resample/test_resample_cases.py @@ -0,0 +1,92 @@ +import copy +import glob +import netCDF4 +import numpy as np +import os +import subprocess +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 casce 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) + subprocess.run(['make'], cwd=this_dir) + + def tearDown(self): + """ + After each test function, remove the input and output netCDF files. + + """ + os.remove('{}/axis_input.nc'.format(this_dir)) + os.remove('{}/axis_output.nc'.format(this_dir)) + + @classmethod + def tearDownClass(cls): + """ + Finally, clean the build the fortran code only once for this class. + + """ + 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) + # run the compiled Fortran XIOS programme + subprocess.run(['mpiexec', '-n', '1', './resample.exe', ':', + '-n', '1', './xios_server.exe'], cwd=this_dir) + # 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)) From b3faa0ba48278b328f010b2832724a986f2fbca8 Mon Sep 17 00:00:00 2001 From: marqh Date: Thu, 25 Jan 2024 15:20:01 +0000 Subject: [PATCH 4/6] MO desktop setup --- desktopEnv | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) 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} From 5c1d32583c83c4c59db63554a9a4bab964f58cab Mon Sep 17 00:00:00 2001 From: marqh Date: Tue, 13 Feb 2024 17:13:57 +0000 Subject: [PATCH 5/6] verMatrix --- .github/workflows/buildTest.yml | 21 ++++++++---- .../read_axis_resample/test_resample_cases.py | 34 +++++++++++++++---- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/.github/workflows/buildTest.yml b/.github/workflows/buildTest.yml index 72c407d..4fbd899 100644 --- a/.github/workflows/buildTest.yml +++ b/.github/workflows/buildTest.yml @@ -1,14 +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, XIOS3/trunk] + version: [XIOS/trunk@2252, XIOS2/trunk] steps: # Check out repository branch - uses: actions/checkout@v4 @@ -42,8 +47,10 @@ jobs: run: | . arch/arch-GCC_LINUX_APT.env . arch/arch-GCC_LINUX_APT.path - export XIOS_BINDIR=$PWD/XIOS2/bin - export XIOS_INCDIR=$PWD/XIOS2/inc - export XIOS_LIBDIR=$PWD/XIOS2/lib + export XIOS_BINDIR=$PWD/XIOS/bin + export XIOS_INCDIR=$PWD/XIOS/inc + export XIOS_LIBDIR=$PWD/XIOS/lib - python3 -m unittest Discover -v -s xios_examples + export MVER=${{ matrix.version }} + + python3 -m unittest discover -v -s xios_examples diff --git a/xios_examples/read_axis_resample/test_resample_cases.py b/xios_examples/read_axis_resample/test_resample_cases.py index 5be2f56..a437086 100644 --- a/xios_examples/read_axis_resample/test_resample_cases.py +++ b/xios_examples/read_axis_resample/test_resample_cases.py @@ -4,6 +4,7 @@ import numpy as np import os import subprocess +import glob import unittest this_path = os.path.realpath(__file__) @@ -12,7 +13,7 @@ class TestResample(unittest.TestCase): """ UnitTest class to contain tests, - 1 test casce function per input `.cdl` file + 1 test case function per input `.cdl` file """ @classmethod @@ -21,14 +22,34 @@ def setUpClass(cls): First, build the fortran code only once for this class. """ - subprocess.run(['make', 'clean'], cwd=this_dir) - subprocess.run(['make'], cwd=this_dir) + 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, remove the input and output netCDF files. + 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)) @@ -59,10 +80,11 @@ def make_a_test(inf): 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) + 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) + '-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') From a634a3e4e2ea1dfa3939914250d54aa12c02a353 Mon Sep 17 00:00:00 2001 From: marqh Date: Mon, 26 Feb 2024 10:46:50 +0000 Subject: [PATCH 6/6] review changes; .PHONY + docstring --- xios_examples/read_axis_resample/Makefile | 2 ++ xios_examples/read_axis_resample/test_resample_cases.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/xios_examples/read_axis_resample/Makefile b/xios_examples/read_axis_resample/Makefile index 0824ec0..dc913c2 100644 --- a/xios_examples/read_axis_resample/Makefile +++ b/xios_examples/read_axis_resample/Makefile @@ -37,6 +37,8 @@ LDFLAGS = \ -lnetcdff \ -lstdc++ +.PHONY: all, clean, run + all: resample # fortran compilation diff --git a/xios_examples/read_axis_resample/test_resample_cases.py b/xios_examples/read_axis_resample/test_resample_cases.py index a437086..93e92b2 100644 --- a/xios_examples/read_axis_resample/test_resample_cases.py +++ b/xios_examples/read_axis_resample/test_resample_cases.py @@ -56,7 +56,7 @@ def tearDown(self): @classmethod def tearDownClass(cls): """ - Finally, clean the build the fortran code only once for this class. + Finally, clean the build for this class, after all tests have run. """ subprocess.run(['make', 'clean'], cwd=this_dir)