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

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

Solve issues for grid mask on server side.

YM

File size: 16.2 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), 
316                                           context->getIntraComm(), client->getRemoteSize()) ;
317    scattererConnector.computeConnector() ;
318   
319    // phase 0
320    // send remote element to construct the full view on server, ie without hole
321    CEventClient event0(getType(), EVENT_ID_SCALAR_DISTRIBUTION);
322    CMessage message0 ;
323    message0<<serverScalarId<<0 ; 
324    remoteElement_[client]->sendToServer(client,event0,message0) ; 
325   
326    // phase 1
327    // send the full view of element to construct the connector which connect distributed data coming from client to the full local view
328    CEventClient event1(getType(), EVENT_ID_SCALAR_DISTRIBUTION);
329    CMessage message1 ;
330    message1<<serverScalarId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
331    scattererConnector.transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
332
333    sendDistributedAttributes(client, scattererConnector, scalarId) ;
334 
335    // phase 2 send the mask : data index + mask2D
336    CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
337    CArray<bool,1> maskOut ;
338    CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
339    workflowToFull.computeConnector() ;
340    maskIn=true ;
341    workflowToFull.transfer(maskIn,maskOut,false) ;
342
343    // phase 3 : prepare grid scatterer connector to send data from client to server
344    map<int,CArray<size_t,1>> workflowGlobalIndex ;
345    map<int,CArray<bool,1>> maskOut2 ; 
346    scattererConnector.transfer(maskOut, maskOut2) ;
347    scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ;
348    scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
349    // create new workflow view for scattered element
350    CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ;
351    clientToServerElement.addFullView() ;
352    CEventClient event2(getType(), EVENT_ID_SCALAR_DISTRIBUTION);
353    CMessage message2 ;
354    message2<<serverScalarId<<2 ; 
355    clientToServerElement.sendToServer(client, event2, message2) ; 
356    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL),
357                                                               context->getIntraComm(), client->getRemoteSize()) ;
358    clientToServerConnector_[client]->computeConnector() ;
359
360    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
361    clientFromServerConnector_[client]->computeConnector() ;
362
363  }
364 
365  void CScalar::recvScalarDistribution(CEventServer& event)
366  TRY
367  {
368    string scalarId;
369    int phasis ;
370    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> scalarId >> phasis ;
371    get(scalarId)->receivedScalarDistribution(event, phasis);
372  }
373  CATCH
374 
375  void CScalar::receivedScalarDistribution(CEventServer& event, int phasis)
376  TRY
377  {
378    CContext* context = CContext::getCurrent();
379    if (phasis==0) // receive the remote element to construct the full view
380    {
381      localElement_ = new  CLocalElement(context->getIntraCommRank(),event) ;
382      localElement_->addFullView() ;
383      // construct the local dimension and indexes
384      auto& globalIndex=localElement_->getGlobalIndex() ;
385      int nk=globalIndex.numElements() ;
386      // no distribution for scalar => nk ==1 or maybe 0 ?
387    }
388    else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server
389    {
390      CContext* context = CContext::getCurrent();
391      CDistributedElement* elementFrom = new  CDistributedElement(event) ;
392      elementFrom->addFullView() ;
393      gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
394      gathererConnector_->computeConnector() ; 
395    }
396    else if (phasis==2)
397    {
398      delete gathererConnector_ ;
399      elementFrom_ = new  CDistributedElement(event) ;
400      elementFrom_->addFullView() ;
401      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
402      gathererConnector_ -> computeConnector() ;
403    }
404  }
405  CATCH
406
407  void CScalar::setServerMask(CArray<bool,1>& serverMask, CContextClient* client)
408  TRY
409  {
410    CContext* context = CContext::getCurrent();
411    localElement_->addView(CElementView::WORKFLOW, serverMask) ;
412    mask = serverMask(0) ;
413 
414    serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ;
415    serverFromClientConnector_->computeConnector() ;
416     
417    serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL),
418                                                         context->getIntraComm(), client->getRemoteSize()) ;
419    serverToClientConnector_->computeConnector() ;
420  }
421  CATCH_DUMP_ATTR
422
423  void CScalar::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& scalarId)
424  {
425    string serverScalarId = scalarId.empty() ? this->getId() : scalarId ;
426    CContext* context = CContext::getCurrent();
427
428    // nothing for now
429  }
430
431  void CScalar::recvDistributedAttributes(CEventServer& event)
432  TRY
433  {
434    string scalarId;
435    string type ;
436    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> scalarId >> type ;
437    get(scalarId)->recvDistributedAttributes(event, type);
438  }
439  CATCH
440
441  void CScalar::recvDistributedAttributes(CEventServer& event, const string& type)
442  TRY
443  {
444    // nothing for now
445  }
446  CATCH 
447
448  bool CScalar::dispatchEvent(CEventServer& event)
449  TRY
450  {
451     if (SuperClass::dispatchEvent(event)) return true;
452     else
453     {
454       switch(event.type)
455       {
456          case EVENT_ID_SCALAR_DISTRIBUTION:
457            recvScalarDistribution(event);
458            return true;
459            break;
460          case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE:
461            recvDistributedAttributes(event);
462            return true;
463            break;
464          default :
465            ERROR("bool CScalar::dispatchEvent(CEventServer& event)",
466                   << "Unknown Event");
467          return false;
468        }
469     }
470  }
471  CATCH
472
473
474  // Definition of some macros
475  DEFINE_REF_FUNC(Scalar,scalar)
476
477} // namespace xios
Note: See TracBrowser for help on using the repository browser.