Changeset 998


Ignore:
Timestamp:
11/19/16 15:19:36 (6 years ago)
Author:
ymipsl
Message:
  • Clarify the situation about filter chaining order between spatial and arithmetics operation :
    • Arithmetic expression is computed first on the source grid
    • Spatial transform is computed after, transforming the result of arithmetics expression on source grid to the target grid.
    • Time filter will be involved on the target grid after spatial transform
  • @this is working now.
  • Add a field attribute "expr" that is equivalent to the XML content describing the arithmetic expression. This attribute can be inherited.

YM

Location:
XIOS/trunk/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • XIOS/trunk/src/config/field_attribute.conf

    r990 r998  
    1111DECLARE_ATTRIBUTE(int,       level) 
    1212DECLARE_ATTRIBUTE(int,       prec) 
     13DECLARE_ATTRIBUTE(StdString, expr) 
    1314 
    1415DECLARE_ATTRIBUTE(bool,      enabled) 
  • XIOS/trunk/src/context_server.cpp

    r887 r998  
    184184         // The best way to properly solve this problem will be to use the event scheduler also in attached mode 
    185185         // for now just set up a MPI barrier 
    186          if (!CServer::eventScheduler) MPI_Barrier(intraComm) ; 
     186         if (!CServer::eventScheduler && CXios::isServer) MPI_Barrier(intraComm) ; 
    187187 
    188188         CTimer::get("Process events").resume(); 
  • XIOS/trunk/src/node/field.cpp

    r989 r998  
    768768   { 
    769769     if (!areAllReferenceSolved) solveAllReferenceEnabledField(false); 
    770  
    771770     // Start by building a filter which can provide the field's instant data 
    772771     if (!instantDataFilter) 
    773772     { 
     773        boost::shared_ptr<COutputPin> arithmDataFilter; 
     774    
    774775       // Check if we have an expression to parse 
    775        if (!content.empty()) 
    776        { 
    777          boost::scoped_ptr<IFilterExprNode> expr(parseExpr(content + '\0')); 
    778          instantDataFilter = expr->reduce(gc, *this); 
    779        } 
    780        // Check if we have a reference on another field 
    781        else if (!field_ref.isEmpty()) 
    782          instantDataFilter = getFieldReference(gc); 
     776       if (hasExpression() || !field_ref.isEmpty()) 
     777       { 
     778         if (hasExpression()) 
     779         { 
     780           boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 
     781           arithmDataFilter = expr->reduce(gc, *this); 
     782         } 
     783         // Check if we have a reference on another field 
     784         if (!field_ref.isEmpty()) instantDataFilter = getFieldReference(gc,arithmDataFilter); 
     785       }   
    783786       // Check if the data is to be read from a file 
    784787       else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 
     
    813816    * \return the output pin corresponding to the field reference 
    814817    */ 
    815    boost::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc) 
     818   boost::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc, boost::shared_ptr<COutputPin> OutputPin) 
    816819   { 
    817820     if (instantDataFilter || field_ref.isEmpty()) 
     
    820823 
    821824     CField* fieldRef = CField::get(field_ref); 
    822      fieldRef->buildFilterGraph(gc, false); 
     825     if (!OutputPin) fieldRef->buildFilterGraph(gc, false); 
    823826 
    824827     std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters; 
     
    834837       filters.first = filters.second = boost::shared_ptr<CFilter>(new CPassThroughFilter(gc)); 
    835838 
    836      fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 
     839     if (!OutputPin)   fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 
     840     else OutputPin->connectOutput(filters.first, 0); 
    837841 
    838842     return filters.second; 
     
    850854   boost::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc) 
    851855   { 
    852      if (instantDataFilter || content.empty()) 
     856     if (instantDataFilter || ! hasExpression()) 
    853857       ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)", 
    854858             "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 
     
    865869       } 
    866870       else if (!field_ref.isEmpty()) 
    867          selfReferenceFilter = getFieldReference(gc); 
     871       { 
     872         CField* fieldRef = CField::get(field_ref); 
     873         fieldRef->buildFilterGraph(gc, false);  
     874         selfReferenceFilter = fieldRef->getInstantDataFilter(); 
     875       } 
    868876       else 
    869877       { 
     
    915923     return it->second; 
    916924   } 
     925 
     926  /*! 
     927    * Returns the temporal filter corresponding to the field's temporal operation 
     928    * for the specified operation frequency. The filter is created if it does not 
     929    * exist, otherwise it is reused. 
     930    * 
     931    * \param gc the garbage collector to use 
     932    * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed 
     933    * \return the output pin corresponding to the requested temporal filter 
     934    */ 
     935    
     936   boost::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 
     937   { 
     938      
     939     if (instantDataFilter || !hasExpression()) 
     940       ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 
     941             "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 
     942 
     943     if (!selfReferenceFilter) getSelfReference(gc) ; 
     944 
     945     if (serverSourceFilter || clientSourceFilter) 
     946     { 
     947       if (operation.isEmpty()) 
     948         ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 
     949               << "An operation must be defined for field \"" << getId() << "\"."); 
     950 
     951       if (freq_op.isEmpty()) freq_op.setValue(TimeStep); 
     952       if (freq_offset.isEmpty()) freq_offset.setValue(NoneDu); 
     953 
     954       const bool ignoreMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 
     955 
     956       boost::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 
     957                                                                             CContext::getCurrent()->getCalendar()->getInitDate(), 
     958                                                                             freq_op, freq_offset, outFreq, 
     959                                                                             ignoreMissingValue, ignoreMissingValue ? default_value : 0.0)); 
     960       selfReferenceFilter->connectOutput(temporalFilter, 0); 
     961       return temporalFilter ; 
     962     } 
     963     else if (!field_ref.isEmpty()) 
     964     { 
     965       CField* fieldRef = CField::get(field_ref); 
     966       fieldRef->buildFilterGraph(gc, false);  
     967       return fieldRef->getTemporalDataFilter(gc, outFreq) ; 
     968     } 
     969  } 
     970 
     971 
     972/* 
     973   boost::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 
     974   { 
     975 
     976       if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 
     977       { 
     978         if (!serverSourceFilter) 
     979           serverSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(grid, 
     980                                                                                   freq_offset.isEmpty() ? NoneDu : freq_offset)); 
     981 
     982         selfReferenceFilter = serverSourceFilter; 
     983       } 
     984       else if (!field_ref.isEmpty()) 
     985       {    
     986          CField* fieldRef = CField::get(field_ref); 
     987          fieldRef->buildFilterGraph(gc, false); 
     988          return fieldRef->getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) ; 
     989       } 
     990   
     991    } 
     992 
     993*/ 
    917994 
    918995   //---------------------------------------------------------------- 
     
    13441421   } 
    13451422 
     1423   /*! 
     1424    * Returns string arithmetic expression associated to the field. 
     1425    * \return if content is defined return content string, otherwise, if "expr" attribute is defined, return expr string. 
     1426    */ 
     1427   string CField::getExpression(void) 
     1428   { 
     1429     if (! expr.isEmpty() && content.empty()) 
     1430     { 
     1431       content=expr ; 
     1432       expr.reset() ; 
     1433     } 
     1434     return content; 
     1435   } 
     1436    
     1437   bool CField::hasExpression(void) 
     1438   { 
     1439     if (! expr.isEmpty()) return true ; 
     1440     if (!content.empty()) return true ; 
     1441     return false; 
     1442   }    
    13461443   DEFINE_REF_FUNC(Field,field) 
    13471444} // namespace xios 
  • XIOS/trunk/src/node/field.hpp

    r989 r998  
    121121 
    122122         void buildFilterGraph(CGarbageCollector& gc, bool enableOutput); 
    123          boost::shared_ptr<COutputPin> getFieldReference(CGarbageCollector& gc); 
     123         boost::shared_ptr<COutputPin> getFieldReference(CGarbageCollector& gc, boost::shared_ptr<COutputPin> OutputPin = boost::shared_ptr<COutputPin>()); 
    124124         boost::shared_ptr<COutputPin> getSelfReference(CGarbageCollector& gc); 
    125125         boost::shared_ptr<COutputPin> getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq); 
     126         boost::shared_ptr<COutputPin> getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq); 
    126127 
    127128//         virtual void fromBinary(StdIStream& is); 
     
    177178 
    178179        const std::vector<StdString>& getRefDomainAxisIds(); 
     180        string getExpression(void) ; 
     181        bool hasExpression(void) ; 
    179182 
    180183      public: 
  • XIOS/trunk/src/node/field_impl.hpp

    r645 r998  
    2020    if (clientSourceFilter) 
    2121      clientSourceFilter->streamData(CContext::getCurrent()->getCalendar()->getCurrentDate(), _data); 
    22     else if (!field_ref.isEmpty() || !content.empty()) 
     22    else if (!field_ref.isEmpty() || hasExpression()) 
    2323      ERROR("void CField::setData(const CArray<double, N>& _data)", 
    2424            << "Impossible to receive data from the model for a field [ id = " << getId() << " ] with a reference or an arithmetic operation."); 
  • XIOS/trunk/src/parse_expr/filter_expr_node.cpp

    r643 r998  
    4040  boost::shared_ptr<COutputPin> CFilterTemporalFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField) const 
    4141  { 
    42     if (!CField::has(fieldId)) 
     42      if (fieldId == "this") return thisField.getSelfTemporalDataFilter(gc, thisField.freq_op.isEmpty() ? TimeStep : thisField.freq_op); 
     43       
     44      if (!CField::has(fieldId)) 
    4345      ERROR("boost::shared_ptr<COutputPin> CFilterTemporalFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField) const", 
    4446            << "The field " << fieldId << " does not exist."); 
    4547 
     48       
    4649    CField* field = CField::get(fieldId); 
    4750    if (field == &thisField) 
Note: See TracChangeset for help on using the changeset viewer.