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

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

Big cleaning on XIOS coupling branch
YM

File size: 15.6 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()
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  /* obsolete, to remove after reimplementing coupling */
156  void CScalar::sendScalarToCouplerOut(CContextClient* client, const string& fieldId, int posInGrid)
157  {
158    if (sendScalarToCouplerOut_done_.count(client)!=0) return ;
159    else sendScalarToCouplerOut_done_.insert(client) ;
160
161    string scalarId="_scalar["+std::to_string(posInGrid)+"]_of_"+fieldId ;
162
163    this->sendAllAttributesToServer(client, scalarId);
164  } 
165
166  void CScalar::makeAliasForCoupling(const string& fieldId, int posInGrid)
167  {
168    const string scalarId = "_scalar["+std::to_string(posInGrid)+"]_of_"+fieldId ;
169    this->createAlias(scalarId) ;
170  }
171
172  void CScalar::setContextClient(CContextClient* contextClient)
173  TRY
174  {
175    if (clientsSet.find(contextClient)==clientsSet.end())
176    {
177      clients.push_back(contextClient) ;
178      clientsSet.insert(contextClient);
179    }
180  }
181  CATCH_DUMP_ATTR
182  /*!
183    Parse children nodes of a scalar in xml file.
184    \param node child node to process
185  */
186  void CScalar::parse(xml::CXMLNode & node)
187  {
188    SuperClass::parse(node);
189
190    if (node.goToChildElement())
191    {
192      StdString nodeElementName;
193      do
194      {
195        StdString nodeId("");
196        if (node.getAttributes().end() != node.getAttributes().find("id"))
197        { nodeId = node.getAttributes()["id"]; }
198
199        nodeElementName = node.getElementName();
200        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
201        it = transformationMapList_.find(nodeElementName);
202        if (ite != it)
203        {
204          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CScalar>::createTransformation(it->second,
205                                                                                                                 nodeId,
206                                                                                                                 &node)));
207        }
208        else
209        {
210          ERROR("void CScalar::parse(xml::CXMLNode & node)",
211                << "The transformation " << nodeElementName << " has not been supported yet.");
212        }
213      } while (node.goToNextElement()) ;
214      node.goToParentElement();
215    }
216  }
217
218   //////////////////////////////////////////////////////////////////////////////////////
219   //  this part is related to distribution, element definition, views and connectors  //
220   //////////////////////////////////////////////////////////////////////////////////////
221
222   void CScalar::initializeLocalElement(void)
223   {
224      // after checkAttribute index of size n
225      int rank = CContext::getCurrent()->getIntraCommRank() ;
226     
227      CArray<size_t,1> ind(1) ;
228      ind(0)=0 ;
229      localElement_ = new CLocalElement(rank, 1, ind) ;
230   }
231
232   void CScalar::addFullView(void)
233   {
234      CArray<int,1> index(1) ;
235      for(int i=0; i<1 ; i++) index(0)=0 ;
236      localElement_ -> addView(CElementView::FULL, index) ;
237   }
238
239   void CScalar::addWorkflowView(void)
240   {
241      CArray<int,1> index ;
242      if (mask) 
243      {
244        index.resize(1) ;
245        index(0)=0 ;
246      }
247      else index.resize(0) ;
248      localElement_ -> addView(CElementView::WORKFLOW, index) ;
249   }
250
251   void CScalar::addModelView(void)
252   {
253     CArray<int,1> index(1) ;
254     for(int i=0; i<1 ; i++) index(0)=0 ;
255     localElement_->addView(CElementView::MODEL, index) ;
256   }
257
258   void CScalar::computeModelToWorkflowConnector(void)
259   { 
260     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
261     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
262     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
263     modelToWorkflowConnector_->computeConnector() ;
264   }
265
266
267  void CScalar::computeRemoteElement(CContextClient* client, EDistributionType type)
268  {
269    CContext* context = CContext::getCurrent();
270    map<int, CArray<size_t,1>> globalIndex ;
271
272    int nbServer = client->serverSize;
273    size_t nglo=1 ;
274    CArray<size_t,1> indGlo(nglo) ;
275    for(size_t i=0;i<nglo;i++) indGlo(i) = i ;
276    for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()) ; 
277
278    remoteElement_[client] = new CDistributedElement(nglo, globalIndex) ;
279    remoteElement_[client]->addFullView() ;
280  }
281 
282  void CScalar::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 
283                                   CScattererConnector* &scattererConnector, const string& scalarId)
284  {
285    string serverScalarId = scalarId.empty() ? this->getId() : scalarId ;
286    CContext* context = CContext::getCurrent();
287
288    this->sendAllAttributesToServer(client, serverScalarId)  ;
289
290    CDistributedElement scatteredElement(1,globalIndex) ;
291    scatteredElement.addFullView() ;
292    scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 
293                                                 context->getIntraComm(), client->getRemoteSize()) ;
294    scattererConnector->computeConnector() ;
295   
296    // phase 0
297    // send remote element to construct the full view on server, ie without hole
298    CEventClient event0(getType(), EVENT_ID_SCALAR_DISTRIBUTION);
299    CMessage message0 ;
300    message0<<serverScalarId<<0 ; 
301    remoteElement_[client]->sendToServer(client,event0,message0) ; 
302   
303    // phase 1
304    // send the full view of element to construct the connector which connect distributed data coming from client to the full local view
305    CEventClient event1(getType(), EVENT_ID_SCALAR_DISTRIBUTION);
306    CMessage message1 ;
307    message1<<serverScalarId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
308    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
309
310    sendDistributedAttributes(client, *scattererConnector, scalarId) ;
311 
312    // phase 2 send the mask : data index + mask2D
313    CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
314    CArray<bool,1> maskOut ;
315    CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
316    workflowToFull.computeConnector() ;
317    maskIn=true ;
318    workflowToFull.transfer(maskIn,maskOut,false) ;
319
320    // phase 3 : prepare grid scatterer connector to send data from client to server
321    map<int,CArray<size_t,1>> workflowGlobalIndex ;
322    map<int,CArray<bool,1>> maskOut2 ; 
323    scattererConnector->transfer(maskOut, maskOut2) ;
324    scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ;
325    scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
326    // create new workflow view for scattered element
327    CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ;
328    clientToServerElement.addFullView() ;
329    CEventClient event2(getType(), EVENT_ID_SCALAR_DISTRIBUTION);
330    CMessage message2 ;
331    message2<<serverScalarId<<2 ; 
332    clientToServerElement.sendToServer(client, event2, message2) ; 
333    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL),
334                                                               context->getIntraComm(), client->getRemoteSize()) ;
335    clientToServerConnector_[client]->computeConnector() ;
336
337    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
338    clientFromServerConnector_[client]->computeConnector() ;
339
340  }
341 
342  void CScalar::recvScalarDistribution(CEventServer& event)
343  TRY
344  {
345    string scalarId;
346    int phasis ;
347    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> scalarId >> phasis ;
348    get(scalarId)->receivedScalarDistribution(event, phasis);
349  }
350  CATCH
351 
352  void CScalar::receivedScalarDistribution(CEventServer& event, int phasis)
353  TRY
354  {
355    CContext* context = CContext::getCurrent();
356    if (phasis==0) // receive the remote element to construct the full view
357    {
358      localElement_ = new  CLocalElement(context->getIntraCommRank(),event) ;
359      localElement_->addFullView() ;
360      // construct the local dimension and indexes
361      auto& globalIndex=localElement_->getGlobalIndex() ;
362      int nk=globalIndex.numElements() ;
363      // no distribution for scalar => nk ==1 or maybe 0 ?
364    }
365    else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server
366    {
367      CContext* context = CContext::getCurrent();
368      CDistributedElement* elementFrom = new  CDistributedElement(event) ;
369      elementFrom->addFullView() ;
370      gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
371      gathererConnector_->computeConnector() ; 
372    }
373    else if (phasis==2)
374    {
375//      delete gathererConnector_ ;
376      elementFrom_ = new  CDistributedElement(event) ;
377      elementFrom_->addFullView() ;
378//      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
379//      gathererConnector_ -> computeConnector() ;
380    }
381  }
382  CATCH
383
384  void CScalar::setServerMask(CArray<bool,1>& serverMask, CContextClient* client)
385  TRY
386  {
387    CContext* context = CContext::getCurrent();
388    localElement_->addView(CElementView::WORKFLOW, serverMask) ;
389    mask = serverMask(0) ;
390 
391    serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ;
392    serverFromClientConnector_->computeConnector() ;
393     
394    serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL),
395                                                         context->getIntraComm(), client->getRemoteSize()) ;
396    serverToClientConnector_->computeConnector() ;
397  }
398  CATCH_DUMP_ATTR
399
400  void CScalar::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& scalarId)
401  {
402    string serverScalarId = scalarId.empty() ? this->getId() : scalarId ;
403    CContext* context = CContext::getCurrent();
404
405    // nothing for now
406  }
407
408  void CScalar::recvDistributedAttributes(CEventServer& event)
409  TRY
410  {
411    string scalarId;
412    string type ;
413    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> scalarId >> type ;
414    get(scalarId)->recvDistributedAttributes(event, type);
415  }
416  CATCH
417
418  void CScalar::recvDistributedAttributes(CEventServer& event, const string& type)
419  TRY
420  {
421    // nothing for now
422  }
423  CATCH 
424
425  bool CScalar::dispatchEvent(CEventServer& event)
426  TRY
427  {
428     if (SuperClass::dispatchEvent(event)) return true;
429     else
430     {
431       switch(event.type)
432       {
433          case EVENT_ID_SCALAR_DISTRIBUTION:
434            recvScalarDistribution(event);
435            return true;
436            break;
437          case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE:
438            recvDistributedAttributes(event);
439            return true;
440            break;
441          default :
442            ERROR("bool CScalar::dispatchEvent(CEventServer& event)",
443                   << "Unknown Event");
444          return false;
445        }
446     }
447  }
448  CATCH
449
450
451  // Definition of some macros
452  DEFINE_REF_FUNC(Scalar,scalar)
453
454} // namespace xios
Note: See TracBrowser for help on using the repository browser.