#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" #include "log.hpp" namespace xios { extern int test_omp_rank; #pragma omp threadprivate(test_omp_rank) MPI_Comm CClient::intraComm ; MPI_Comm CClient::interComm ; std::list *CClient::contextInterComms_ptr = 0; int CClient::serverLeader ; bool CClient::is_MPI_Initialized ; int CClient::rank = INVALID_RANK; StdOFStream CClient::m_infoStream; StdOFStream CClient::m_errorStream; StdOFStream CClient::array_infoStream[16]; 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 ; // don't use OASIS if (!CXios::usingOasis) { // localComm doesn't given if (localComm == MPI_COMM_NULL) { if (!is_MPI_Initialized) { //MPI_Init(NULL, NULL); int return_level; MPI_Init_thread(NULL, NULL, 3, &return_level); assert(return_level == 3); } 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_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;iinitClient(contextComm,contextInterComm) ; if(contextInterComms_ptr == NULL) contextInterComms_ptr = new std::list; contextInterComms_ptr->push_back(contextInterComm); MPI_Comm_free(&inter); } else { 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); if(contextInterComms_ptr == NULL) contextInterComms_ptr = new std::list; contextInterComms_ptr->push_back(contextInterComm); } } 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_ptr->begin(); it != contextInterComms_ptr->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(); } #pragma omp critical (_output) info(20) << "Client "<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(); info_FB[omp_get_thread_num()] = array_infoStream[omp_get_thread_num()].rdbuf(); openStream(fileName, ".out", info_FB[omp_get_thread_num()]); info.write2File(info_FB[omp_get_thread_num()]); report.write2File(info_FB[omp_get_thread_num()]); } //! 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(); } }