#include "globalScopeData.hpp" #include "xios_spl.hpp" #include "cxios.hpp" #include "client.hpp" #include #include "type.hpp" #include "context.hpp" #include "context_client.hpp" #include "oasis_cinterface.hpp" #include "mpi.hpp" #include "timer.hpp" #include "buffer_client.hpp" namespace xios { MPI_Comm CClient::intraComm ; MPI_Comm CClient::interComm ; std::list CClient::contextInterComms; int CClient::serverLeader ; bool CClient::is_MPI_Initialized ; int CClient::rank_ = INVALID_RANK; StdOFStream CClient::m_infoStream; StdOFStream CClient::m_errorStream; MPI_Comm& CClient::getInterComm(void) { return (interComm); } ///--------------------------------------------------------------- /*! * \fn void CClient::initialize(const string& codeId, MPI_Comm& localComm, MPI_Comm& returnComm) * Function creates intraComm (CClient::intraComm) for client group with id=codeId and interComm (CClient::interComm) between client and server groups. * \param [in] codeId identity of context. * \param [in/out] localComm local communicator. * \param [in/out] returnComm (intra)communicator of client group. */ void CClient::initialize(const string& codeId, MPI_Comm& localComm, MPI_Comm& returnComm) { int initialized ; MPI_Initialized(&initialized) ; if (initialized) is_MPI_Initialized=true ; else is_MPI_Initialized=false ; int rank ; // don't use OASIS if (!CXios::usingOasis) { // localComm isn't given if (localComm == MPI_COMM_NULL) { if (!is_MPI_Initialized) { MPI_Init(NULL, NULL); } CTimer::get("XIOS").resume() ; CTimer::get("XIOS init/finalize").resume() ; boost::hash hashString ; unsigned long hashClient=hashString(codeId) ; unsigned long hashServer=hashString(CXios::xiosCodeId) ; unsigned long* hashAll ; int size ; int myColor ; int i,c ; MPI_Comm newComm ; MPI_Comm_size(CXios::globalComm,&size) ; MPI_Comm_rank(CXios::globalComm,&rank_); hashAll=new unsigned long[size] ; MPI_Allgather(&hashClient,1,MPI_LONG,hashAll,1,MPI_LONG,CXios::globalComm) ; map colors ; map leaders ; for(i=0,c=0;ihasServer) // Attached mode { MPI_Comm contextInterComm ; MPI_Comm_dup(contextComm,&contextInterComm) ; CContext* contextServer = CContext::create(idServer); // Firstly, initialize context on client side context->initClient(contextComm,contextInterComm, contextServer); // Secondly, initialize context on server side contextServer->initServer(contextComm,contextInterComm, context); // Finally, we should return current context to context client CContext::setCurrent(id); contextInterComms.push_back(contextInterComm); } else { int size,rank,globalRank ; size_t message_size ; int leaderRank ; MPI_Comm contextInterComm ; MPI_Comm_size(contextComm,&size) ; MPI_Comm_rank(contextComm,&rank) ; MPI_Comm_rank(CXios::globalComm,&globalRank) ; if (rank!=0) globalRank=0 ; CMessage msg ; msg<initClient(contextComm,contextInterComm) ; contextInterComms.push_back(contextInterComm); MPI_Comm_free(&inter); delete [] buff ; } } void CClient::finalize(void) { int rank ; int msg=0 ; MPI_Comm_rank(intraComm,&rank) ; if (!CXios::isServer) { MPI_Comm_rank(intraComm,&rank) ; if (rank==0) { MPI_Send(&msg,1,MPI_INT,0,0,interComm) ; } } for (std::list::iterator it = contextInterComms.begin(); it != contextInterComms.end(); it++) MPI_Comm_free(&(*it)); MPI_Comm_free(&interComm); MPI_Comm_free(&intraComm); CTimer::get("XIOS init/finalize").suspend() ; CTimer::get("XIOS").suspend() ; if (!is_MPI_Initialized) { if (CXios::usingOasis) oasis_finalize(); else MPI_Finalize() ; } info(20) << "Client side context is finalized"<open(fileNameClient.str().c_str(), std::ios::out); if (!fb->is_open()) ERROR("void CClient::openStream(const StdString& fileName, const StdString& ext, std::filebuf* fb)", << std::endl << "Can not open <" << fileNameClient << "> file to write the client log(s)."); } /*! * \brief Open a file stream to write the info logs * Open a file stream with a specific file name suffix+rank * to write the info logs. * \param fileName [in] protype file name */ void CClient::openInfoStream(const StdString& fileName) { std::filebuf* fb = m_infoStream.rdbuf(); openStream(fileName, ".out", fb); info.write2File(fb); report.write2File(fb); } //! Write the info logs to standard output void CClient::openInfoStream() { info.write2StdOut(); report.write2StdOut(); } //! Close the info logs file if it opens void CClient::closeInfoStream() { if (m_infoStream.is_open()) m_infoStream.close(); } /*! * \brief Open a file stream to write the error log * Open a file stream with a specific file name suffix+rank * to write the error log. * \param fileName [in] protype file name */ void CClient::openErrorStream(const StdString& fileName) { std::filebuf* fb = m_errorStream.rdbuf(); openStream(fileName, ".err", fb); error.write2File(fb); } //! Write the error log to standard error output void CClient::openErrorStream() { error.write2StdErr(); } //! Close the error log file if it opens void CClient::closeErrorStream() { if (m_errorStream.is_open()) m_errorStream.close(); } }