#include "field.hpp" #include "attribute_template.hpp" #include "object_template.hpp" #include "group_template.hpp" #include "node_type.hpp" #include "calendar_util.hpp" #include "message.hpp" #include "xmlioserver_spl.hpp" #include "type.hpp" #include "context_client.hpp" namespace xios{ /// ////////////////////// Définitions ////////////////////// /// CField::CField(void) : CObjectTemplate(), CFieldAttributes() , refObject(), baseRefObject() , grid(), file() , freq_operation(), freq_write() , nstep(0) , last_Write(), last_operation() , foperation() , data(new CArray(boost::extents[0])) { /* Ne rien faire de plus */ } CField::CField(const StdString & id) : CObjectTemplate(id), CFieldAttributes() , refObject(), baseRefObject() , grid(), file() , freq_operation(), freq_write() , nstep(0) , last_Write(), last_operation() , foperation() , data(new CArray(boost::extents[0])) { /* Ne rien faire de plus */ } CField::~CField(void) { // this->grid.reset() ; // this->file.reset() ; this->foperation.reset() ; this->data.reset() ; } //---------------------------------------------------------------- bool CField::updateDataServer (const CDate & currDate, const std::deque storedClient) { const CDate opeDate = *last_operation + freq_operation; const CDate writeDate = *last_Write + freq_write; if (opeDate <= currDate) { if (this->data->num_elements() != this->grid->storeIndex[0]->num_elements()) { this->data->resize(boost::extents[this->grid->storeIndex[0] ->num_elements()]); } ARRAY_CREATE(input, double, 1, [this->data->num_elements()]); this->grid->inputFieldServer(storedClient, input); (*this->foperation)(input); *last_operation = currDate; } if (writeDate < (currDate + freq_operation)) { this->foperation->final(); this->incrementNStep(); *last_Write = writeDate; return (true); } return (false); } bool CField::dispatchEvent(CEventServer& event) { if (SuperClass::dispatchEvent(event)) return true ; else { switch(event.type) { case EVENT_ID_UPDATE_DATA : recvUpdateData(event) ; return true ; break ; default : ERROR("bool CField::dispatchEvent(CEventServer& event)",<<"Unknown Event") ; return false ; } } } void CField::sendUpdateData(void) { CContext* context = CContext::getCurrent() ; CContextClient* client=context->client ; CEventClient event(getType(),EVENT_ID_UPDATE_DATA) ; map::iterator it ; list > list_msg ; list list_data ; for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++) { int rank=(*it).first ; ARRAY(int,1) index=(*it).second ; ARRAY_CREATE(data_tmp,double,1,[index->num_elements()]) ; for(int n=0;nnum_elements();n++) (*data_tmp)[n]=(*data)[(*index)[n]] ; list_msg.push_back(shared_ptr(new CMessage)) ; list_data.push_back(data_tmp) ; *list_msg.back()<nbSenders[rank],*list_msg.back()) ; } client->sendEvent(event) ; } void CField::recvUpdateData(CEventServer& event) { vector ranks ; vector buffers ; list::iterator it ; string fieldId ; for (it=event.subEvents.begin();it!=event.subEvents.end();++it) { int rank=it->rank; CBufferIn* buffer=it->buffer; *buffer>>fieldId ; ranks.push_back(rank) ; buffers.push_back(buffer) ; } get(fieldId)->recvUpdateData(ranks,buffers) ; } void CField::recvUpdateData(vector& ranks, vector& buffers) { if (data_srv.empty()) { for(map::iterator it=grid->out_i_fromClient.begin();it!=grid->out_i_fromClient.end();it++) { int rank=it->first ; ARRAY_CREATE(data_tmp,double,1,[it->second->num_elements()]) ; data_srv.insert(pair(rank,data_tmp)) ; foperation_srv.insert(pair >(rank,boost::shared_ptr(new func::CInstant(data_srv[rank])))) ; } } CContext* context = CContext::getCurrent() ; const CDate & currDate = context->getCalendar()->getCurrentDate(); const CDate opeDate = *last_operation_srv + freq_operation_srv; const CDate writeDate = *last_Write_srv + freq_write_srv; if (opeDate <= currDate) { for(int n=0;n>data_tmp ; (*foperation_srv[ranks[n]])(data_tmp) ; } *last_operation_srv = currDate; } if (writeDate < (currDate + freq_operation_srv)) { for(int n=0;nfoperation_srv[ranks[n]]->final(); } *last_Write_srv = writeDate; writeField() ; *lastlast_Write_srv=*last_Write_srv; } } void CField::writeField(void) { if (! grid->domain->isEmpty() || getRelFile()->type.getValue()=="one_file") { getRelFile()->checkFile(); this->incrementNStep(); getRelFile()->getDataOutput()->writeFieldData(CField::get(this)); } } //---------------------------------------------------------------- void CField::setRelFile(CFile* _file) { this->file = _file; } //---------------------------------------------------------------- StdString CField::GetName(void) { return (StdString("field")); } StdString CField::GetDefName(void){ return (CField::GetName()); } ENodeType CField::GetType(void) { return (eField); } //---------------------------------------------------------------- CGrid* CField::getRelGrid(void) const { return (this->grid); } //---------------------------------------------------------------- CFile* CField::getRelFile(void) const { return (this->file); } StdSize CField::getNStep(void) const { return (this->nstep); } void CField::incrementNStep(void) { this->nstep++; } void CField::resetNStep(void) { this->nstep=0; } //---------------------------------------------------------------- CField* CField::getDirectFieldReference(void) const { if (this->field_ref.isEmpty()) return (this->getBaseFieldReference()); if (! CField::has(this->field_ref.getValue())) ERROR("CField::getDirectFieldReference(void)", << "[ ref_name = " << this->field_ref.getValue() << "]" << " invalid field name !"); return (CField::get(this->field_ref.getValue())); } //---------------------------------------------------------------- CField* CField::getBaseFieldReference(void) const { return (baseRefObject); } //---------------------------------------------------------------- const std::vector& CField::getAllReference(void) const { return (refObject); } //---------------------------------------------------------------- const StdString & CField::getBaseFieldId(void) const { return (this->getBaseFieldReference()->getId()); } //---------------------------------------------------------------- const CDuration & CField::getFreqOperation(void) const { return (this->freq_operation); } //---------------------------------------------------------------- const CDuration & CField::getFreqWrite(void) const { return (this->freq_write); } //---------------------------------------------------------------- boost::shared_ptr CField::getFieldOperation(void) const { return (this->foperation); } //---------------------------------------------------------------- bool CField::hasDirectFieldReference(void) const { return (!this->field_ref.isEmpty()); } bool CField::isActive(void) const { return (!this->refObject.empty()); } //---------------------------------------------------------------- ARRAY(double, 1) CField::getData(void) const { return(this->data); } //---------------------------------------------------------------- boost::shared_ptr CField::getLastWriteDate(void) const { return(this->last_Write); } //---------------------------------------------------------------- boost::shared_ptr CField::getLastOperationDate(void) const { return(this->last_operation); } //---------------------------------------------------------------- void CField::solveRefInheritance(void) { std::set sset; CField* refer_sptr; CField * refer_ptr = this; this->baseRefObject = CField::get(this); while (refer_ptr->hasDirectFieldReference()) { refer_sptr = refer_ptr->getDirectFieldReference(); refer_ptr = refer_sptr; if(sset.end() != sset.find(refer_ptr)) { DEBUG (<< "Dépendance circulaire stoppée pour l'objet de type CField sur " << "\"" + refer_ptr->getId() + "\" !"); break; } SuperClassAttribute::setAttributes(refer_ptr); sset.insert(refer_ptr); baseRefObject = refer_sptr; //ym refObject.push_back(refer_sptr); } } //---------------------------------------------------------------- void CField::solveOperation(void) { using namespace func; StdString id = this->getBaseFieldReference()->getId(); CContext* context = CContext::getCurrent(); if (operation.isEmpty() || freq_op.isEmpty() || this->file->output_freq.isEmpty()) { ERROR("CField::solveOperation(void)", << "[ id = " << id << "]" << "Impossible de définir une opération pour le champ !"); } CDuration freq_offset_ = NoneDu; if (!freq_offset.isEmpty()) { freq_offset_ = CDuration::FromString(freq_offset.getValue()); } else { freq_offset.setValue(NoneDu.toString()); } // if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER) if (context->hasServer) { this->freq_operation_srv = CDuration::FromString(this->file->output_freq.getValue()); this->freq_write_srv = CDuration::FromString(this->file->output_freq.getValue()); this->lastlast_Write_srv = boost::shared_ptr (new CDate(context->getCalendar()->getInitDate())); this->last_Write_srv = boost::shared_ptr (new CDate(context->getCalendar()->getInitDate())); this->last_operation_srv = boost::shared_ptr (new CDate(context->getCalendar()->getInitDate())); // this->foperation_srv = // boost::shared_ptr(new CInstant(this->data_srv)); const CDuration toffset = this->freq_operation_srv - freq_offset_ - context->getCalendar()->getTimeStep(); *this->last_operation_srv = *this->last_operation_srv - toffset; } if (context->hasClient) { this->freq_operation = CDuration::FromString(freq_op.getValue()); this->freq_write = CDuration::FromString(this->file->output_freq.getValue()); this->last_Write = boost::shared_ptr (new CDate(context->getCalendar()->getInitDate())); this->last_operation = boost::shared_ptr (new CDate(context->getCalendar()->getInitDate())); const CDuration toffset = this->freq_operation - freq_offset_ - context->getCalendar()->getTimeStep(); *this->last_operation = *this->last_operation - toffset; #define DECLARE_FUNCTOR(MType, mtype) \ if (operation.getValue().compare(#mtype) == 0) \ { \ boost::shared_ptr \ foperation_(new C##MType(this->data)); \ this->foperation = foperation_; \ return; \ } #include "functor_type.conf" ERROR("CField::solveOperation(void)", << "[ operation = " << operation.getValue() << "]" << "L'opération n'est pas définie dans le code !"); } } //---------------------------------------------------------------- void CField::fromBinary(StdIStream & is) { SuperClass::fromBinary(is); #define CLEAR_ATT(name_)\ SuperClassAttribute::operator[](#name_)->clear() CLEAR_ATT(domain_ref); CLEAR_ATT(axis_ref); #undef CLEAR_ATT } //---------------------------------------------------------------- void CField::solveGridReference(void) { CDomain* domain; CAxis* axis; if (!domain_ref.isEmpty()) { if (CDomain::has(domain_ref.getValue())) domain = CDomain::get(domain_ref.getValue()) ; else ERROR("CField::solveGridReference(void)", << "Référence au domaine nommé \'" << domain_ref.getValue() << "\' incorrecte") ; } if (!axis_ref.isEmpty()) { if (CAxis::has(axis_ref.getValue())) axis = CAxis::get(axis_ref.getValue()) ; else ERROR("CField::solveGridReference(void)", << "Référence à l'axe nommé \'" << axis_ref.getValue() <<"\' incorrecte") ; } if (!grid_ref.isEmpty()) { if (CGrid::has(grid_ref.getValue())) this->grid = CGrid::get(grid_ref.getValue()) ; else ERROR("CField::solveGridReference(void)", << "Référence à la grille nommée \'" << grid_ref.getValue() << "\' incorrecte"); if (!domain_ref.isEmpty()) DEBUG(<< "Définition conjointe de la grille " << "et du domaine, la grille prévaut..." ); if (!axis_ref.isEmpty()) DEBUG(<< "Définition conjointe de la grille " << "et de l'axe vertical, la grille prévaut...") ; } else { if (!domain_ref.isEmpty()) { if (!axis_ref.isEmpty()) { this->grid = CGrid::createGrid(domain, axis) ; this->grid_ref.setValue(this->grid->getId()); } else { this->grid = CGrid::createGrid(domain) ; this->grid_ref.setValue(this->grid->getId()); } } else { ERROR("CField::solveGridReference(void)", << "Le domaine horizontal pour le champ X n'est pas défini"); } } grid->solveReference() ; } ///------------------------------------------------------------------- template <> void CGroupTemplate::solveRefInheritance(void) { if (this->group_ref.isEmpty()) return; StdString gref = this->group_ref.getValue(); if (!CFieldGroup::has(gref)) ERROR("CGroupTemplate::solveRefInheritance(void)", << "[ gref = " << gref << "]" << " invalid group name !"); CFieldGroup* group = CFieldGroup::get(gref); CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast(this)); std::vector allChildren = group->getAllChildren(); std::vector::iterator it = allChildren.begin(), end = allChildren.end(); for (; it != end; it++) { CField* child = *it; if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()) ; } } void CField::outputField(ARRAY(double,3) fieldOut) { map::iterator it; for(it=data_srv.begin();it!=data_srv.end();it++) grid->outputField(it->first,it->second, fieldOut) ; } void CField::outputField(ARRAY(double,2) fieldOut) { map::iterator it; for(it=data_srv.begin();it!=data_srv.end();it++) { grid->outputField(it->first,it->second, fieldOut) ; } } ///------------------------------------------------------------------- } // namespace xios