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

Last change on this file since 1940 was 1940, checked in by ymipsl, 4 years ago

Xios coupling branch

  • Update connectors mechanism for scalar, similarly for domain and axis
  • add mask attribute to scalar

YM

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