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

Last change on this file since 2196 was 2196, checked in by jderouillat, 3 years ago

Backporting commit 1852 : Compiler fix for recent version of GCCfor optimised mode > O1

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