source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/scalar.cpp @ 2203

Last change on this file since 2203 was 2203, checked in by ymipsl, 3 years ago

New functionnality : domain, axis and scalar can now be retrieve with new syntax id :
ex. for domain :

id="domainId" : old syntax, working as before
id="fieldId::domainId" : get the domain related to "domainId" associated to the field "fieldId", work if only 1 domain related to domainId is associated to the field.
id="fieldId::domainId[n]" : get the nth domain related to "domainId" associated to the field "fieldId"
id="fieldId::" : get the domain associated the the field "fieldId, work if grid associated to th field is composed with exactly 1 domain (and possibly other components axis or scalars)
id="fieldId::[n] : get the nth domain composing the grid associated to the field

YM

File size: 17.7 KB
Line 
1#include "scalar.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6#include "object_factory.hpp"
7#include "xios_spl.hpp"
8#include "type.hpp"
9#include "context.hpp"
10
11#include <algorithm>
12#include <regex>
13
14namespace xios
15{
16
17  /// ////////////////////// Définitions ////////////////////// ///
18
19  CScalar::CScalar(void)
20     : CObjectTemplate<CScalar>()
21     , CScalarAttributes()
22     , relFiles()
23  { /* Ne rien faire de plus */ }
24
25  CScalar::CScalar(const StdString & id)
26     : CObjectTemplate<CScalar>(id)
27     , CScalarAttributes()
28     , relFiles()
29  { /* Ne rien faire de plus */ }
30
31  CScalar::~CScalar(void)
32  { /* Ne rien faire de plus */ }
33
34  std::map<StdString, ETranformationType> CScalar::transformationMapList_ = std::map<StdString, ETranformationType>();
35  bool CScalar::dummyTransformationMapList_ = CScalar::initializeTransformationMap(CScalar::transformationMapList_);
36  bool CScalar::initializeTransformationMap(std::map<StdString, ETranformationType>& m)
37  {
38    m["reduce_axis"]   = TRANS_REDUCE_AXIS_TO_SCALAR;
39    m["extract_axis"]  = TRANS_EXTRACT_AXIS_TO_SCALAR;
40    m["reduce_domain"] = TRANS_REDUCE_DOMAIN_TO_SCALAR;
41    m["reduce_scalar"] = TRANS_REDUCE_SCALAR_TO_SCALAR;
42    return true;
43  }
44
45  StdString CScalar::GetName(void)   { return (StdString("scalar")); }
46  StdString CScalar::GetDefName(void){ return (CScalar::GetName()); }
47  ENodeType CScalar::GetType(void)   { return (eScalar); }
48
49  CScalar* CScalar::createScalar()
50  {
51    CScalar* scalar = CScalarGroup::get("scalar_definition")->createChild();
52    return scalar;
53  }
54
55  CScalar* CScalar::get(const string& id)
56  {
57    const regex r("::");
58    smatch m;
59    if (regex_search(id, m, r))
60    {
61      if (m.size()!=1) ERROR("CScalar* CScalar::get(string& id)", <<" id = "<<id<< "  -> bad format id, separator :: append more than one time");
62      string fieldId=m.prefix() ;
63      if (fieldId.empty()) ERROR("CScalar* CScalar::get(string& id)", <<" id = "<<id<< "  -> bad format id, field name is empty");
64      string suffix=m.suffix() ;
65      CField* field=CField::get(fieldId) ;
66      return field->getAssociatedScalar(suffix) ;
67    }
68    else return CObjectFactory::GetObject<CScalar>(id).get();
69  }
70
71  bool CScalar::IsWritten(const StdString & filename) const
72  {
73    return (this->relFiles.find(filename) != this->relFiles.end());
74  }
75
76  void CScalar::addRelFile(const StdString& filename)
77  {
78      this->relFiles.insert(filename);
79  }
80
81  void CScalar::checkAttributes(void)
82  {
83    if (checkAttributes_done_) return ;
84    checkAttributes_done_ = true ; 
85
86    if (mask.isEmpty()) mask=true ;
87
88    initializeLocalElement() ;
89    addFullView() ;
90    addWorkflowView() ;
91    addModelView() ;
92  }
93
94  /*!
95    Compare two scalar objects.
96    They are equal if only if they have identical attributes as well as their values.
97    Moreover, they must have the same transformations.
98  \param [in] scalar Compared scalar
99  \return result of the comparison
100  */
101  bool CScalar::isEqual(CScalar* obj)
102  {
103    vector<StdString> excludedAttr;
104    excludedAttr.push_back("scalar_ref");
105    bool objEqual = SuperClass::isEqual(obj, excludedAttr);
106    if (!objEqual) return objEqual;
107
108    TransMapTypes thisTrans = this->getAllTransformations();
109    TransMapTypes objTrans  = obj->getAllTransformations();
110
111    TransMapTypes::const_iterator it, itb, ite;
112    std::vector<ETranformationType> thisTransType, objTransType;
113    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
114      thisTransType.push_back(it->first);
115    for (it = objTrans.begin(); it != objTrans.end(); ++it)
116      objTransType.push_back(it->first);
117
118    if (thisTransType.size() != objTransType.size()) return false;
119    for (int idx = 0; idx < thisTransType.size(); ++idx)
120      objEqual &= (thisTransType[idx] == objTransType[idx]);
121
122    return objEqual;
123  }
124
125  CTransformation<CScalar>* CScalar::addTransformation(ETranformationType transType, const StdString& id)
126  {
127    transformationMap_.push_back(std::make_pair(transType, CTransformation<CScalar>::createTransformation(transType,id)));
128    return transformationMap_.back().second;
129  }
130
131  bool CScalar::hasTransformation()
132  {
133    return (!transformationMap_.empty());
134  }
135
136  void CScalar::setTransformations(const TransMapTypes& scalarTrans)
137  {
138    transformationMap_ = scalarTrans;
139  }
140
141  CScalar::TransMapTypes CScalar::getAllTransformations(void)
142  {
143    return transformationMap_;
144  }
145
146  void CScalar::duplicateTransformation(CScalar* src)
147  {
148    if (src->hasTransformation())
149    {
150      this->setTransformations(src->getAllTransformations());
151    }
152  }
153
154  /*!
155   * Go through the hierarchy to find the scalar from which the transformations must be inherited
156   */
157  void CScalar::solveInheritanceTransformation_old()
158  {
159    if (hasTransformation() || !hasDirectScalarReference())
160      return;
161
162    CScalar* scalar = this;
163    std::vector<CScalar*> refScalar;
164    while (!scalar->hasTransformation() && scalar->hasDirectScalarReference())
165    {
166      refScalar.push_back(scalar);
167      scalar = scalar->getDirectScalarReference();
168    }
169
170    if (scalar->hasTransformation())
171      for (size_t i = 0; i < refScalar.size(); ++i)
172        refScalar[i]->setTransformations(scalar->getAllTransformations());
173  }
174 
175  void CScalar::solveInheritanceTransformation()
176  TRY
177  {
178    if (solveInheritanceTransformation_done_) return;
179    else solveInheritanceTransformation_done_=true ;
180
181    CScalar* scalar = this;
182    CScalar* Lastscalar ;
183    std::list<CScalar*> refScalars;
184    bool out=false ;
185    vector<StdString> excludedAttr;
186    excludedAttr.push_back("scalar_ref");
187   
188    refScalars.push_front(scalar) ;
189    while (scalar->hasDirectScalarReference() && !out)
190    {
191      CScalar* lastScalar=scalar ;
192      scalar = scalar->getDirectScalarReference();
193      scalar->solveRefInheritance() ;
194      if (!scalar->SuperClass::isEqual(lastScalar,excludedAttr)) out=true ;
195      refScalars.push_front(scalar) ;
196    }
197
198    CTransformationPaths::TPath path ;
199    auto& pathList = std::get<2>(path) ;
200    std::get<0>(path) = EElement::SCALAR ;
201    std::get<1>(path) = refScalars.front()->getId() ;
202    for (auto& scalar : refScalars)
203    {
204      CScalar::TransMapTypes transformations = scalar->getAllTransformations();
205      for(auto& transformation : transformations) pathList.push_back({transformation.second->getTransformationType(), 
206                                                                      transformation.second->getId()}) ;
207    }
208    transformationPaths_.addPath(path) ;
209
210  }
211  CATCH_DUMP_ATTR
212
213  /* obsolete, to remove after reimplementing coupling */
214  void CScalar::sendScalarToCouplerOut(CContextClient* client, const string& fieldId, int posInGrid)
215  {
216    if (sendScalarToCouplerOut_done_.count(client)!=0) return ;
217    else sendScalarToCouplerOut_done_.insert(client) ;
218
219    string scalarId = getCouplingAlias(fieldId, posInGrid) ;
220
221    this->sendAllAttributesToServer(client, scalarId);
222  } 
223
224  string CScalar::getCouplingAlias(const string& fieldId, int posInGrid)
225  {
226    return "_scalar["+std::to_string(posInGrid)+"]_of_"+fieldId ;
227  }
228
229  void CScalar::makeAliasForCoupling(const string& fieldId, int posInGrid)
230  {
231    const string scalarId = getCouplingAlias(fieldId, posInGrid) ;
232    this->createAlias(scalarId) ;
233  }
234
235  void CScalar::setContextClient(CContextClient* contextClient)
236  TRY
237  {
238    if (clientsSet.find(contextClient)==clientsSet.end())
239    {
240      clients.push_back(contextClient) ;
241      clientsSet.insert(contextClient);
242    }
243  }
244  CATCH_DUMP_ATTR
245  /*!
246    Parse children nodes of a scalar in xml file.
247    \param node child node to process
248  */
249  void CScalar::parse(xml::CXMLNode & node)
250  {
251    SuperClass::parse(node);
252
253    if (node.goToChildElement())
254    {
255      StdString nodeElementName;
256      do
257      {
258        StdString nodeId("");
259        if (node.getAttributes().end() != node.getAttributes().find("id"))
260        { nodeId = node.getAttributes()["id"]; }
261
262        nodeElementName = node.getElementName();
263        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
264        it = transformationMapList_.find(nodeElementName);
265        if (ite != it)
266        {
267          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CScalar>::createTransformation(it->second,
268                                                                                                                 nodeId,
269                                                                                                                 &node)));
270        }
271        else
272        {
273          ERROR("void CScalar::parse(xml::CXMLNode & node)",
274                << "The transformation " << nodeElementName << " has not been supported yet.");
275        }
276      } while (node.goToNextElement()) ;
277      node.goToParentElement();
278    }
279  }
280
281   //////////////////////////////////////////////////////////////////////////////////////
282   //  this part is related to distribution, element definition, views and connectors  //
283   //////////////////////////////////////////////////////////////////////////////////////
284
285   void CScalar::initializeLocalElement(void)
286   {
287      // after checkAttribute index of size n
288      int rank = CContext::getCurrent()->getIntraCommRank() ;
289     
290      CArray<size_t,1> ind(1) ;
291      ind(0)=0 ;
292      localElement_ = new CLocalElement(rank, 1, ind) ;
293   }
294
295   void CScalar::addFullView(void)
296   {
297      CArray<int,1> index(1) ;
298      for(int i=0; i<1 ; i++) index(0)=0 ;
299      localElement_ -> addView(CElementView::FULL, index) ;
300   }
301
302   void CScalar::addWorkflowView(void)
303   {
304      CArray<int,1> index ;
305      if (mask) 
306      {
307        index.resize(1) ;
308        index(0)=0 ;
309      }
310      else index.resize(0) ;
311      localElement_ -> addView(CElementView::WORKFLOW, index) ;
312   }
313
314   void CScalar::addModelView(void)
315   {
316     CArray<int,1> index(1) ;
317     for(int i=0; i<1 ; i++) index(0)=0 ;
318     localElement_->addView(CElementView::MODEL, index) ;
319   }
320
321   void CScalar::computeModelToWorkflowConnector(void)
322   { 
323     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
324     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
325     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
326     modelToWorkflowConnector_->computeConnector() ;
327   }
328
329
330  void CScalar::computeRemoteElement(CContextClient* client, EDistributionType type)
331  {
332    CContext* context = CContext::getCurrent();
333    map<int, CArray<size_t,1>> globalIndex ;
334
335    int nbServer = client->serverSize;
336    size_t nglo=1 ;
337    CArray<size_t,1> indGlo(nglo) ;
338    for(size_t i=0;i<nglo;i++) indGlo(i) = i ;
339    for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()) ; 
340
341    remoteElement_[client] = new CDistributedElement(nglo, globalIndex) ;
342    remoteElement_[client]->addFullView() ;
343  }
344 
345  void CScalar::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 
346                                   CScattererConnector* &scattererConnector, const string& scalarId)
347  {
348    string serverScalarId = scalarId.empty() ? this->getId() : scalarId ;
349    CContext* context = CContext::getCurrent();
350
351    this->sendAllAttributesToServer(client, serverScalarId)  ;
352
353    CDistributedElement scatteredElement(1,globalIndex) ;
354    scatteredElement.addFullView() ;
355    scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 
356                                                 context->getIntraComm(), client->getRemoteSize()) ;
357    scattererConnector->computeConnector() ;
358   
359    // phase 0
360    // send remote element to construct the full view on server, ie without hole
361    CEventClient event0(getType(), EVENT_ID_SCALAR_DISTRIBUTION);
362    CMessage message0 ;
363    message0<<serverScalarId<<0 ; 
364    remoteElement_[client]->sendToServer(client,event0,message0) ; 
365   
366    // phase 1
367    // send the full view of element to construct the connector which connect distributed data coming from client to the full local view
368    CEventClient event1(getType(), EVENT_ID_SCALAR_DISTRIBUTION);
369    CMessage message1 ;
370    message1<<serverScalarId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
371    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
372
373    sendDistributedAttributes(client, *scattererConnector, scalarId) ;
374 
375    // phase 2 send the mask : data index + mask2D
376    CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
377    CArray<bool,1> maskOut ;
378    CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
379    workflowToFull.computeConnector() ;
380    maskIn=true ;
381    workflowToFull.transfer(maskIn,maskOut,false) ;
382
383    // phase 3 : prepare grid scatterer connector to send data from client to server
384    map<int,CArray<size_t,1>> workflowGlobalIndex ;
385    map<int,CArray<bool,1>> maskOut2 ; 
386    scattererConnector->transfer(maskOut, maskOut2) ;
387    scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ;
388    scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
389    // create new workflow view for scattered element
390    CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ;
391    clientToServerElement.addFullView() ;
392    CEventClient event2(getType(), EVENT_ID_SCALAR_DISTRIBUTION);
393    CMessage message2 ;
394    message2<<serverScalarId<<2 ; 
395    clientToServerElement.sendToServer(client, event2, message2) ; 
396    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL),
397                                                               context->getIntraComm(), client->getRemoteSize()) ;
398    clientToServerConnector_[client]->computeConnector() ;
399
400    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
401    clientFromServerConnector_[client]->computeConnector() ;
402
403  }
404 
405  void CScalar::recvScalarDistribution(CEventServer& event)
406  TRY
407  {
408    string scalarId;
409    int phasis ;
410    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> scalarId >> phasis ;
411    get(scalarId)->receivedScalarDistribution(event, phasis);
412  }
413  CATCH
414 
415  void CScalar::receivedScalarDistribution(CEventServer& event, int phasis)
416  TRY
417  {
418    CContext* context = CContext::getCurrent();
419    if (phasis==0) // receive the remote element to construct the full view
420    {
421      localElement_ = new  CLocalElement(context->getIntraCommRank(),event) ;
422      localElement_->addFullView() ;
423      // construct the local dimension and indexes
424      auto& globalIndex=localElement_->getGlobalIndex() ;
425      int nk=globalIndex.numElements() ;
426      // no distribution for scalar => nk ==1 or maybe 0 ?
427    }
428    else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server
429    {
430      CContext* context = CContext::getCurrent();
431      CDistributedElement* elementFrom = new  CDistributedElement(event) ;
432      elementFrom->addFullView() ;
433      gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
434      gathererConnector_->computeConnector() ; 
435    }
436    else if (phasis==2)
437    {
438//      delete gathererConnector_ ;
439      elementFrom_ = new  CDistributedElement(event) ;
440      elementFrom_->addFullView() ;
441//      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
442//      gathererConnector_ -> computeConnector() ;
443    }
444  }
445  CATCH
446
447  void CScalar::setServerMask(CArray<bool,1>& serverMask, CContextClient* client)
448  TRY
449  {
450    CContext* context = CContext::getCurrent();
451    localElement_->addView(CElementView::WORKFLOW, serverMask) ;
452    mask = serverMask(0) ;
453 
454    serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ;
455    serverFromClientConnector_->computeConnector() ;
456     
457    serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL),
458                                                         context->getIntraComm(), client->getRemoteSize()) ;
459    serverToClientConnector_->computeConnector() ;
460  }
461  CATCH_DUMP_ATTR
462
463  void CScalar::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& scalarId)
464  {
465    string serverScalarId = scalarId.empty() ? this->getId() : scalarId ;
466    CContext* context = CContext::getCurrent();
467
468    // nothing for now
469  }
470
471  void CScalar::recvDistributedAttributes(CEventServer& event)
472  TRY
473  {
474    string scalarId;
475    string type ;
476    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> scalarId >> type ;
477    get(scalarId)->recvDistributedAttributes(event, type);
478  }
479  CATCH
480
481  void CScalar::recvDistributedAttributes(CEventServer& event, const string& type)
482  TRY
483  {
484    // nothing for now
485  }
486  CATCH 
487
488  bool CScalar::dispatchEvent(CEventServer& event)
489  TRY
490  {
491     if (SuperClass::dispatchEvent(event)) return true;
492     else
493     {
494       switch(event.type)
495       {
496          case EVENT_ID_SCALAR_DISTRIBUTION:
497            recvScalarDistribution(event);
498            return true;
499            break;
500          case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE:
501            recvDistributedAttributes(event);
502            return true;
503            break;
504          default :
505            ERROR("bool CScalar::dispatchEvent(CEventServer& event)",
506                   << "Unknown Event");
507          return false;
508        }
509     }
510  }
511  CATCH
512
513
514  // Definition of some macros
515  DEFINE_REF_FUNC(Scalar,scalar)
516
517} // namespace xios
Note: See TracBrowser for help on using the repository browser.