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

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

intermediate commit for new tranformation engine?
YM

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