source: codes/icosagcm/branches/SATURN_DYNAMICO/XIOS/src/node/file.cpp @ 312

Last change on this file since 312 was 312, checked in by ymipsl, 10 years ago

Add splitting suffix in XIOS in second rather than terrestrial date.

YM

  • Property svn:eol-style set to native
File size: 19.5 KB
Line 
1#include "file.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6#include "object_factory.hpp"
7#include "data_output.hpp"
8#include "context.hpp"
9#include "context_server.hpp"
10#include "nc4_data_output.hpp"
11#include "calendar_util.hpp"
12#include "date.hpp"
13#include "message.hpp"
14#include "type.hpp"
15#include "xmlioserver_spl.hpp"
16#include "context_client.hpp"
17#include "mpi.hpp"
18
19namespace xios {
20   
21   /// ////////////////////// Définitions ////////////////////// ///
22
23   CFile::CFile(void)
24      : CObjectTemplate<CFile>(), CFileAttributes()
25      , vFieldGroup(), data_out(), enabledFields(), fileComm(MPI_COMM_NULL)
26   { 
27     setVirtualFieldGroup() ;
28     setVirtualVariableGroup() ;
29   }
30
31   CFile::CFile(const StdString & id)
32      : CObjectTemplate<CFile>(id), CFileAttributes()
33      , vFieldGroup(), data_out(), enabledFields(), fileComm(MPI_COMM_NULL)
34    { 
35      setVirtualFieldGroup() ;
36      setVirtualVariableGroup() ;
37    }
38
39   CFile::~CFile(void)
40   { /* Ne rien faire de plus */ }
41
42   ///---------------------------------------------------------------
43
44   StdString CFile::GetName(void)   { return (StdString("file")); }
45   StdString CFile::GetDefName(void){ return (CFile::GetName()); }
46   ENodeType CFile::GetType(void)   { return (eFile); }
47
48   //----------------------------------------------------------------
49
50   boost::shared_ptr<CDataOutput> CFile::getDataOutput(void) const
51   {
52      return (data_out);
53   }
54
55   CFieldGroup* CFile::getVirtualFieldGroup(void) const
56   {
57      return (this->vFieldGroup);
58   }
59
60   CVariableGroup* CFile::getVirtualVariableGroup(void) const
61   {
62      return (this->vVariableGroup);
63   }
64
65   std::vector<CField*> CFile::getAllFields(void) const
66   {
67      return (this->vFieldGroup->getAllChildren());
68   }
69 
70   std::vector<CVariable*> CFile::getAllVariables(void) const
71   {
72      return (this->vVariableGroup->getAllChildren());
73   }
74
75   //----------------------------------------------------------------
76
77   std::vector<CField*> CFile::getEnabledFields(int default_outputlevel, 
78                                                int default_level,
79                                                bool default_enabled)
80   {
81      if (!this->enabledFields.empty())
82         return (this->enabledFields);
83
84      const int _outputlevel =
85         (!output_level.isEmpty()) ? output_level.getValue() : default_outputlevel;
86      std::vector<CField*>::iterator it;
87      this->enabledFields = this->getAllFields();
88
89      std::vector<CField*> newEnabledFields;
90     
91      for ( it = this->enabledFields.begin() ; it != this->enabledFields.end(); it++ )
92      {
93         if (!(*it)->enabled.isEmpty()) // Si l'attribut 'enabled' est défini ...
94         {
95            if (! (*it)->enabled.getValue()) continue;
96//            { it--; this->enabledFields.erase(it+1); continue; }
97         }
98         else // Si l'attribut 'enabled' n'est pas défini ...
99         {
100            if (!default_enabled) continue ;
101//            { it--; this->enabledFields.erase(it+1); continue; }
102         }
103
104         if (!(*it)->level.isEmpty()) // Si l'attribut 'level' est défini ...
105         {
106            if ((*it)->level.getValue() > _outputlevel) continue ;
107//            { it--; this->enabledFields.erase(it+1); continue; }
108         }
109         else // Si l'attribut 'level' n'est pas défini ...
110         {
111            if (default_level > _outputlevel) continue ;
112//            { it--; this->enabledFields.erase(it+1); continue; }
113         }
114 
115//         CField* field_tmp=(*it).get() ;
116//         shared_ptr<CField> sptfield=*it ;
117//         field_tmp->refObject.push_back(sptfield) ;
118         newEnabledFields.push_back(*it) ;
119         // Le champ est finalement actif, on y ajoute sa propre reference.
120//         (*it)->refObject.push_back(*it);
121         // Le champ est finalement actif, on y ajoute la référence au champ de base.
122         (*it)->setRelFile(CFile::get(this));
123//         (*it)->baseRefObject->refObject.push_back(*it);
124         // A faire, ajouter les references intermediaires...
125      }
126      enabledFields=newEnabledFields ;
127
128      return (this->enabledFields);
129   }
130
131   //----------------------------------------------------------------
132
133   void CFile::setVirtualFieldGroup(CFieldGroup* newVFieldGroup)
134   { 
135      this->vFieldGroup = newVFieldGroup; 
136   }
137
138   void CFile::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
139   { 
140      this->vVariableGroup = newVVariableGroup; 
141   }
142
143   //----------------------------------------------------------------
144
145   void CFile::setVirtualFieldGroup(void)
146   {
147      this->setVirtualFieldGroup(CFieldGroup::create());
148   }
149
150   void CFile::setVirtualVariableGroup(void)
151   {
152      this->setVirtualVariableGroup(CVariableGroup::create());
153   }
154
155   //----------------------------------------------------------------
156   bool CFile::isSyncTime(void)
157   {
158     CContext* context = CContext::getCurrent() ;
159     CDate& currentDate=context->calendar->getCurrentDate() ;
160     if (! sync_freq.isEmpty())
161     {
162       if (*lastSync+syncFreq < currentDate)
163       {
164         *lastSync=currentDate ;
165         return true ;
166        }
167      }
168      return false ;
169    }
170   
171   void CFile::initFile(void)
172   {
173      CContext* context = CContext::getCurrent() ;
174      CDate& currentDate=context->calendar->getCurrentDate() ;
175      CContextServer* server=context->server ;
176           
177      if (! sync_freq.isEmpty()) syncFreq = CDuration::FromString(sync_freq.getValue());
178      if (! split_freq.isEmpty()) splitFreq = CDuration::FromString(split_freq.getValue());
179      if (! output_freq.isEmpty()) outputFreq = CDuration::FromString(output_freq.getValue());
180      lastSync=new CDate(currentDate) ;
181      lastSplit=new CDate(currentDate) ;
182      isOpen=false ;
183
184      allDomainEmpty=true ;
185      set<CDomain*> setDomain ;
186
187      std::vector<CField*>::iterator it, end = this->enabledFields.end();
188      for (it = this->enabledFields.begin() ;it != end; it++)
189      {
190         CField* field = *it;
191         allDomainEmpty&=field->grid->domain->isEmpty() ;
192         setDomain.insert(field->grid->domain) ;
193      }
194      nbDomain=setDomain.size() ;
195
196      // create sub communicator for file 
197      int color=allDomainEmpty?0:1 ;
198      MPI_Comm_split(server->intraComm,color,server->intraCommRank,&fileComm) ;
199      if (allDomainEmpty) MPI_Comm_free(&fileComm) ;
200      //
201     
202    }
203   
204    void CFile::checkFile(void)
205    {
206      if (!isOpen) createHeader() ;
207      checkSync() ;
208      checkSplit() ;
209    }
210     
211     
212   bool CFile::checkSync(void)
213   {
214     CContext* context = CContext::getCurrent() ;
215     CDate& currentDate=context->calendar->getCurrentDate() ;
216     if (! sync_freq.isEmpty())
217     {
218       if (*lastSync+syncFreq <= currentDate)
219       {
220         *lastSync=currentDate ;
221         data_out->syncFile() ;
222         return true ;
223        }
224      }
225      return false ;
226    }
227   
228   
229    bool CFile::checkSplit(void)
230    {
231      CContext* context = CContext::getCurrent() ;
232      CDate& currentDate=context->calendar->getCurrentDate() ;
233      if (! split_freq.isEmpty())
234      {
235        if (currentDate > *lastSplit+splitFreq)
236        {
237          *lastSplit=*lastSplit+splitFreq ;   
238          std::vector<CField*>::iterator it, end = this->enabledFields.end();
239          for (it = this->enabledFields.begin() ;it != end; it++)  (*it)->resetNStep() ;
240          createHeader() ;
241          return true ;
242        }
243      }
244      return false ;
245    }
246   
247   void CFile::createHeader(void)
248   {
249      CContext* context = CContext::getCurrent() ;
250      CContextServer* server=context->server ;
251     
252      if (!allDomainEmpty)
253      {
254         StdString filename = (!name.isEmpty()) ?   name.getValue() : getId();
255         StdOStringStream oss;
256         oss << filename;
257         if (!name_suffix.isEmpty()) oss << name_suffix.getValue();
258//         if (!split_freq.isEmpty()) oss<<"_"<<lastSplit->getStryyyymmdd()<<"-"<< (*lastSplit+(splitFreq-1*Second)).getStryyyymmdd();
259//         if (!split_freq.isEmpty()) oss<<"_"<<lastSplit->getStr("%y_%mo_%d")<<"-"<< (*lastSplit+(splitFreq-1*Second)).getStr("%y_%mo_%d");
260         if (!split_freq.isEmpty())
261         {
262           string splitFormat ;
263           if (split_freq_format.isEmpty())
264           {
265             if (splitFreq.second!=0) splitFormat="%y%mo%d%h%mi%s";
266             else if (splitFreq.minute!=0) splitFormat="%y%mo%d%h%mi";
267             else if (splitFreq.hour!=0) splitFormat="%y%mo%d%h";
268             else if (splitFreq.day!=0) splitFormat="%y%mo%d";
269             else if (splitFreq.month!=0) splitFormat="%y%mo";
270             else splitFormat="%y";
271           }
272           else splitFormat=split_freq_format ;
273//           oss<<"_"<<lastSplit->getStr(splitFormat)<<"-"<< (*lastSplit+(splitFreq-1*Second)).getStr(splitFormat);
274            oss<<"_"<< Time(*lastSplit)-Time(context->calendar->getTimeOrigin())
275               <<"-"<<Time(*lastSplit+(splitFreq-1*Second))-Time(context->calendar->getTimeOrigin());
276         }
277           
278         bool multifile=true ;
279         if (!type.isEmpty())
280         {
281           if (type==type_attr::one_file) multifile=false ;
282           else if (type==type_attr::multiple_file) multifile=true ;
283
284         } 
285#ifndef USING_NETCDF_PAR
286         if (!multifile)
287         {
288            info(0)<<"!!! Warning -> Using non parallel version of netcdf, switching in multiple_file mode for file : "<<filename<<" ..."<<endl ;
289            multifile=true ;
290          }
291#endif
292         if (multifile) 
293         {
294            int commSize, commRank ;
295            MPI_Comm_size(fileComm,&commSize) ;
296            MPI_Comm_rank(fileComm,&commRank) ;
297           
298            if (server->intraCommSize > 1) 
299            {
300              oss << "_"  ;
301              int width=0 ; int n=commSize-1 ;
302              while(n != 0) { n=n/10 ; width++ ;}
303              if (!min_digits.isEmpty()) 
304                if (width<min_digits) width=min_digits ;
305              oss.width(width) ;
306              oss.fill('0') ;
307              oss<<right<< commRank;
308            }
309         }
310         oss << ".nc";
311
312         if (isOpen) data_out->closeFile() ;
313         bool isCollective=true ;
314         if (!par_access.isEmpty())
315         {
316           if (par_access.getValue()=="independent") isCollective=false ;
317           else if (par_access.getValue()=="collective") isCollective=true ;
318           else 
319           {
320             ERROR("void Context::createDataOutput(void)",
321                        "incorrect file <par_access> attribut : must be <collective> or <indepedent>, "
322                        <<"having : <"<<type.getValue()<<">") ;
323           }
324         }
325         data_out=shared_ptr<CDataOutput>(new CNc4DataOutput(oss.str(), false, fileComm, multifile, isCollective));
326         isOpen=true ;
327
328         data_out->writeFile(CFile::get(this));
329         std::vector<CField*>::iterator it, end = this->enabledFields.end();
330         for (it = this->enabledFields.begin() ;it != end; it++)
331         {
332            CField* field = *it;
333            this->data_out->writeFieldGrid(field);
334         }
335         this->data_out->writeTimeDimension();
336         
337         for (it = this->enabledFields.begin() ;it != end; it++)
338         {
339            CField* field = *it;
340            this->data_out->writeField(field);
341         }
342         
343         vector<CVariable*> listVars = getAllVariables() ;
344         for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) this-> data_out-> writeAttribute(*it) ;
345         
346         this->data_out->definition_end();
347      }
348   }
349
350   void CFile::close(void)
351   {
352     delete lastSync ;
353     delete lastSplit ;
354     if (!allDomainEmpty)
355       if (isOpen) 
356       {
357         this->data_out->closeFile();
358       }
359      if (fileComm != MPI_COMM_NULL) MPI_Comm_free(&fileComm) ;
360   }
361   //----------------------------------------------------------------
362
363   void CFile::parse(xml::CXMLNode & node)
364   {
365      SuperClass::parse(node);
366     
367      if (node.goToChildElement())
368      {
369        do
370        {
371           if (node.getElementName()=="field" || node.getElementName()=="field_group") this->getVirtualFieldGroup()->parseChild(node);
372           else if (node.getElementName()=="variable" || node.getElementName()=="variable_group") this->getVirtualVariableGroup()->parseChild(node);
373        } while (node.goToNextElement()) ;
374        node.goToParentElement();
375      }
376
377   }
378   //----------------------------------------------------------------
379
380   StdString CFile::toString(void) const
381   {
382      StdOStringStream oss;
383
384      oss << "<" << CFile::GetName() << " ";
385      if (this->hasId())
386         oss << " id=\"" << this->getId() << "\" ";
387      oss << SuperClassAttribute::toString() << ">" << std::endl;
388      if (this->getVirtualFieldGroup() != NULL)
389         oss << *this->getVirtualFieldGroup() << std::endl;
390      oss << "</" << CFile::GetName() << " >";
391      return (oss.str());
392   }
393
394   //----------------------------------------------------------------
395   
396   void CFile::solveDescInheritance(bool apply, const CAttributeMap * const parent)
397   {
398      SuperClassAttribute::setAttributes(parent,apply);
399      this->getVirtualFieldGroup()->solveDescInheritance(apply, NULL); 
400      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
401   }
402
403   //----------------------------------------------------------------
404
405   void CFile::processEnabledFile(void)
406   {
407     if (output_freq.isEmpty()) ERROR("void CFile::processEnabledFile(void)",
408                                       <<"File attribute <<output_freq>> is undefined"); 
409     solveFieldRefInheritance(true) ;
410     getEnabledFields() ;
411     processEnabledFields() ;
412   }
413   
414   void CFile::processEnabledFields(void)
415   {
416      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
417      {
418        this->enabledFields[i]->processEnabledField() ;
419      }
420    }
421   
422   void CFile::solveFieldRefInheritance(bool apply)
423   {
424      // Résolution des héritages par référence de chacun des champs contenus dans le fichier.
425      std::vector<CField*> allF = this->getAllFields();
426      for (unsigned int i = 0; i < allF.size(); i++)
427         allF[i]->solveRefInheritance(apply);
428   }
429
430   //----------------------------------------------------------------
431
432   void CFile::solveEFGridRef(void)
433   {
434      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
435         this->enabledFields[i]->solveGridReference();
436   }
437
438   //----------------------------------------------------------------
439
440   void CFile::solveEFOperation(void)
441   {
442      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
443         this->enabledFields[i]->solveOperation();
444   }
445 
446   void CFile::solveEFExpression(void)
447   {
448      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
449         this->enabledFields[i]->buildExpression();
450   }   
451 
452
453   CField* CFile::addField(const string& id)
454   {
455     return vFieldGroup->createChild(id) ;
456   }
457
458   CFieldGroup* CFile::addFieldGroup(const string& id)
459   {
460     return vFieldGroup->createChildGroup(id) ;
461   }
462 
463   CVariable* CFile::addVariable(const string& id)
464   {
465     return vVariableGroup->createChild(id) ;
466   }
467
468   CVariableGroup* CFile::addVariableGroup(const string& id)
469   {
470     return vVariableGroup->createChildGroup(id) ;
471   }
472   
473 
474   void CFile::sendAddField(const string& id)
475   {
476    CContext* context=CContext::getCurrent() ;
477   
478    if (! context->hasServer )
479    {
480       CContextClient* client=context->client ;
481
482       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD) ;   
483       if (client->isServerLeader())
484       {
485         CMessage msg ;
486         msg<<this->getId() ;
487         msg<<id ;
488         event.push(client->getServerLeader(),1,msg) ;
489         client->sendEvent(event) ;
490       }
491       else client->sendEvent(event) ;
492    }
493     
494   }
495   
496   void CFile::sendAddFieldGroup(const string& id)
497   {
498    CContext* context=CContext::getCurrent() ;
499    if (! context->hasServer )
500    {
501       CContextClient* client=context->client ;
502
503       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD_GROUP) ;   
504       if (client->isServerLeader())
505       {
506         CMessage msg ;
507         msg<<this->getId() ;
508         msg<<id ;
509         event.push(client->getServerLeader(),1,msg) ;
510         client->sendEvent(event) ;
511       }
512       else client->sendEvent(event) ;
513    }
514     
515   }
516   
517   void CFile::recvAddField(CEventServer& event)
518   {
519     
520      CBufferIn* buffer=event.subEvents.begin()->buffer;
521      string id;
522      *buffer>>id ;
523      get(id)->recvAddField(*buffer) ;
524   }
525   
526   
527   void CFile::recvAddField(CBufferIn& buffer)
528   {
529      string id ;
530      buffer>>id ;
531      addField(id) ;
532   }
533
534   void CFile::recvAddFieldGroup(CEventServer& event)
535   {
536     
537      CBufferIn* buffer=event.subEvents.begin()->buffer;
538      string id;
539      *buffer>>id ;
540      get(id)->recvAddFieldGroup(*buffer) ;
541   }
542   
543   
544   void CFile::recvAddFieldGroup(CBufferIn& buffer)
545   {
546      string id ;
547      buffer>>id ;
548      addFieldGroup(id) ;
549   }
550   
551
552
553
554
555
556
557
558
559
560
561   void CFile::sendAddVariable(const string& id)
562   {
563    CContext* context=CContext::getCurrent() ;
564   
565    if (! context->hasServer )
566    {
567       CContextClient* client=context->client ;
568
569       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE) ;   
570       if (client->isServerLeader())
571       {
572         CMessage msg ;
573         msg<<this->getId() ;
574         msg<<id ;
575         event.push(client->getServerLeader(),1,msg) ;
576         client->sendEvent(event) ;
577       }
578       else client->sendEvent(event) ;
579    }
580     
581   }
582   
583   void CFile::sendAddVariableGroup(const string& id)
584   {
585    CContext* context=CContext::getCurrent() ;
586    if (! context->hasServer )
587    {
588       CContextClient* client=context->client ;
589
590       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP) ;   
591       if (client->isServerLeader())
592       {
593         CMessage msg ;
594         msg<<this->getId() ;
595         msg<<id ;
596         event.push(client->getServerLeader(),1,msg) ;
597         client->sendEvent(event) ;
598       }
599       else client->sendEvent(event) ;
600    }
601     
602   }
603   
604   void CFile::recvAddVariable(CEventServer& event)
605   {
606     
607      CBufferIn* buffer=event.subEvents.begin()->buffer;
608      string id;
609      *buffer>>id ;
610      get(id)->recvAddVariable(*buffer) ;
611   }
612   
613   
614   void CFile::recvAddVariable(CBufferIn& buffer)
615   {
616      string id ;
617      buffer>>id ;
618      addVariable(id) ;
619   }
620
621   void CFile::recvAddVariableGroup(CEventServer& event)
622   {
623     
624      CBufferIn* buffer=event.subEvents.begin()->buffer;
625      string id;
626      *buffer>>id ;
627      get(id)->recvAddVariableGroup(*buffer) ;
628   }
629   
630   
631   void CFile::recvAddVariableGroup(CBufferIn& buffer)
632   {
633      string id ;
634      buffer>>id ;
635      addVariableGroup(id) ;
636   }
637
638
639
640
641
642   bool CFile::dispatchEvent(CEventServer& event)
643   {
644      if (SuperClass::dispatchEvent(event)) return true ;
645      else
646      {
647        switch(event.type)
648        {
649           case EVENT_ID_ADD_FIELD :
650             recvAddField(event) ;
651             return true ;
652             break ;
653         
654           case EVENT_ID_ADD_FIELD_GROUP :
655             recvAddFieldGroup(event) ;
656             return true ;
657             break ;       
658 
659            case EVENT_ID_ADD_VARIABLE :
660             recvAddVariable(event) ;
661             return true ;
662             break ;
663         
664           case EVENT_ID_ADD_VARIABLE_GROUP :
665             recvAddVariableGroup(event) ;
666             return true ;
667             break ;               
668           default :
669              ERROR("bool CFile::dispatchEvent(CEventServer& event)", <<"Unknown Event") ;
670           return false ;
671        }
672      }
673   }
674   
675   
676   
677   
678   ///---------------------------------------------------------------
679
680} // namespace xios
Note: See TracBrowser for help on using the repository browser.