1 | #include "axis.hpp" |
---|
2 | |
---|
3 | #include "attribute_template.hpp" |
---|
4 | #include "object_template.hpp" |
---|
5 | #include "group_template.hpp" |
---|
6 | #include "message.hpp" |
---|
7 | #include "type.hpp" |
---|
8 | #include "context.hpp" |
---|
9 | #include "context_client.hpp" |
---|
10 | #include "context_server.hpp" |
---|
11 | #include "xios_spl.hpp" |
---|
12 | #include "server_distribution_description.hpp" |
---|
13 | #include "client_server_mapping_distributed.hpp" |
---|
14 | #include "distribution_client.hpp" |
---|
15 | |
---|
16 | namespace xios { |
---|
17 | |
---|
18 | /// ////////////////////// Definitions ////////////////////// /// |
---|
19 | |
---|
20 | CAxis::CAxis(void) |
---|
21 | : CObjectTemplate<CAxis>() |
---|
22 | , CAxisAttributes(), isChecked(false), relFiles(), areClientAttributesChecked_(false) |
---|
23 | , isClientAfterTransformationChecked(false) |
---|
24 | , hasBounds(false), isCompressible_(false) |
---|
25 | , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_() |
---|
26 | , transformationMap_(), hasValue(false), hasLabel(false) |
---|
27 | , computedWrittenIndex_(false) |
---|
28 | , clients() |
---|
29 | { |
---|
30 | } |
---|
31 | |
---|
32 | CAxis::CAxis(const StdString & id) |
---|
33 | : CObjectTemplate<CAxis>(id) |
---|
34 | , CAxisAttributes(), isChecked(false), relFiles(), areClientAttributesChecked_(false) |
---|
35 | , isClientAfterTransformationChecked(false) |
---|
36 | , hasBounds(false), isCompressible_(false) |
---|
37 | , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_() |
---|
38 | , transformationMap_(), hasValue(false), hasLabel(false) |
---|
39 | , computedWrittenIndex_(false) |
---|
40 | , clients() |
---|
41 | { |
---|
42 | } |
---|
43 | |
---|
44 | CAxis::~CAxis(void) |
---|
45 | { /* Ne rien faire de plus */ } |
---|
46 | |
---|
47 | std::map<StdString, ETranformationType> CAxis::transformationMapList_ = std::map<StdString, ETranformationType>(); |
---|
48 | bool CAxis::dummyTransformationMapList_ = CAxis::initializeTransformationMap(CAxis::transformationMapList_); |
---|
49 | bool CAxis::initializeTransformationMap(std::map<StdString, ETranformationType>& m) |
---|
50 | TRY |
---|
51 | { |
---|
52 | m["zoom_axis"] = TRANS_ZOOM_AXIS; |
---|
53 | m["interpolate_axis"] = TRANS_INTERPOLATE_AXIS; |
---|
54 | m["extract_axis"] = TRANS_EXTRACT_AXIS; |
---|
55 | m["inverse_axis"] = TRANS_INVERSE_AXIS; |
---|
56 | m["reduce_domain"] = TRANS_REDUCE_DOMAIN_TO_AXIS; |
---|
57 | m["reduce_axis"] = TRANS_REDUCE_AXIS_TO_AXIS; |
---|
58 | m["extract_domain"] = TRANS_EXTRACT_DOMAIN_TO_AXIS; |
---|
59 | m["temporal_splitting"] = TRANS_TEMPORAL_SPLITTING; |
---|
60 | m["duplicate_scalar"] = TRANS_DUPLICATE_SCALAR_TO_AXIS; |
---|
61 | |
---|
62 | } |
---|
63 | CATCH |
---|
64 | |
---|
65 | ///--------------------------------------------------------------- |
---|
66 | |
---|
67 | const std::set<StdString> & CAxis::getRelFiles(void) const |
---|
68 | TRY |
---|
69 | { |
---|
70 | return (this->relFiles); |
---|
71 | } |
---|
72 | CATCH |
---|
73 | |
---|
74 | bool CAxis::IsWritten(const StdString & filename) const |
---|
75 | TRY |
---|
76 | { |
---|
77 | return (this->relFiles.find(filename) != this->relFiles.end()); |
---|
78 | } |
---|
79 | CATCH |
---|
80 | |
---|
81 | bool CAxis::isWrittenCompressed(const StdString& filename) const |
---|
82 | TRY |
---|
83 | { |
---|
84 | return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end()); |
---|
85 | } |
---|
86 | CATCH |
---|
87 | |
---|
88 | bool CAxis::isDistributed(void) const |
---|
89 | TRY |
---|
90 | { |
---|
91 | bool distributed = (!this->begin.isEmpty() && !this->n.isEmpty() && (this->begin + this->n < this->n_glo)) || |
---|
92 | (!this->n.isEmpty() && (this->n != this->n_glo)); |
---|
93 | // A condition to make sure that if there is only one client, axis |
---|
94 | // should be considered to be distributed. This should be a temporary solution |
---|
95 | distributed |= (1 == CContext::getCurrent()->intraCommSize_); |
---|
96 | return distributed; |
---|
97 | } |
---|
98 | CATCH |
---|
99 | |
---|
100 | /*! |
---|
101 | * Compute if the axis can be ouput in a compressed way. |
---|
102 | * In this case the workflow view on server side must be the same |
---|
103 | * than the full view for all context rank. The result is stored on |
---|
104 | * internal isCompressible_ attribute. |
---|
105 | */ |
---|
106 | void CAxis::computeIsCompressible(void) |
---|
107 | TRY |
---|
108 | { |
---|
109 | // mesh is compressible contains some masked or indexed value, ie if full view is different of workflow view. |
---|
110 | // But now assume that the size of the 2 view must be equal for everybody. True on server side |
---|
111 | int isSameView = getLocalView(CElementView::FULL)->getSize() == getLocalView(CElementView::WORKFLOW)->getSize(); |
---|
112 | MPI_Allreduce(MPI_IN_PLACE, &isSameView, 1, MPI_INT, MPI_LAND, CContext::getCurrent()->getIntraComm()) ; |
---|
113 | if (isSameView) isCompressible_ = false ; |
---|
114 | else isCompressible_ = true ; |
---|
115 | isCompressibleComputed_=true ; |
---|
116 | } |
---|
117 | CATCH |
---|
118 | |
---|
119 | void CAxis::addRelFile(const StdString & filename) |
---|
120 | TRY |
---|
121 | { |
---|
122 | this->relFiles.insert(filename); |
---|
123 | } |
---|
124 | CATCH_DUMP_ATTR |
---|
125 | |
---|
126 | void CAxis::addRelFileCompressed(const StdString& filename) |
---|
127 | TRY |
---|
128 | { |
---|
129 | this->relFilesCompressed.insert(filename); |
---|
130 | } |
---|
131 | CATCH_DUMP_ATTR |
---|
132 | |
---|
133 | //---------------------------------------------------------------- |
---|
134 | |
---|
135 | /*! |
---|
136 | Returns the number of indexes written by each server. |
---|
137 | \return the number of indexes written by each server |
---|
138 | */ |
---|
139 | int CAxis::getNumberWrittenIndexes(MPI_Comm writtenCom) |
---|
140 | TRY |
---|
141 | { |
---|
142 | int writtenSize; |
---|
143 | MPI_Comm_size(writtenCom, &writtenSize); |
---|
144 | return numberWrittenIndexes_[writtenSize]; |
---|
145 | } |
---|
146 | CATCH_DUMP_ATTR |
---|
147 | |
---|
148 | /*! |
---|
149 | Returns the total number of indexes written by the servers. |
---|
150 | \return the total number of indexes written by the servers |
---|
151 | */ |
---|
152 | int CAxis::getTotalNumberWrittenIndexes(MPI_Comm writtenCom) |
---|
153 | TRY |
---|
154 | { |
---|
155 | int writtenSize; |
---|
156 | MPI_Comm_size(writtenCom, &writtenSize); |
---|
157 | return totalNumberWrittenIndexes_[writtenSize]; |
---|
158 | } |
---|
159 | CATCH_DUMP_ATTR |
---|
160 | |
---|
161 | /*! |
---|
162 | Returns the offset of indexes written by each server. |
---|
163 | \return the offset of indexes written by each server |
---|
164 | */ |
---|
165 | int CAxis::getOffsetWrittenIndexes(MPI_Comm writtenCom) |
---|
166 | TRY |
---|
167 | { |
---|
168 | int writtenSize; |
---|
169 | MPI_Comm_size(writtenCom, &writtenSize); |
---|
170 | return offsetWrittenIndexes_[writtenSize]; |
---|
171 | } |
---|
172 | CATCH_DUMP_ATTR |
---|
173 | |
---|
174 | CArray<int, 1>& CAxis::getCompressedIndexToWriteOnServer(MPI_Comm writtenCom) |
---|
175 | TRY |
---|
176 | { |
---|
177 | int writtenSize; |
---|
178 | MPI_Comm_size(writtenCom, &writtenSize); |
---|
179 | return compressedIndexToWriteOnServer[writtenSize]; |
---|
180 | } |
---|
181 | CATCH_DUMP_ATTR |
---|
182 | |
---|
183 | //---------------------------------------------------------------- |
---|
184 | |
---|
185 | /*! |
---|
186 | * Compute the minimum buffer size required to send the attributes to the server(s). |
---|
187 | * |
---|
188 | * \return A map associating the server rank with its minimum buffer size. |
---|
189 | */ |
---|
190 | std::map<int, StdSize> CAxis::getAttributesBufferSize(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, |
---|
191 | CServerDistributionDescription::ServerDistributionType distType) |
---|
192 | TRY |
---|
193 | { |
---|
194 | |
---|
195 | std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client); |
---|
196 | |
---|
197 | // bool isNonDistributed = (n_glo == n); |
---|
198 | bool isDistributed = (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType)) |
---|
199 | || (index.numElements() != n_glo); |
---|
200 | |
---|
201 | if (client->isServerLeader()) |
---|
202 | { |
---|
203 | // size estimation for sendServerAttribut |
---|
204 | size_t size = 6 * sizeof(size_t); |
---|
205 | // size estimation for sendNonDistributedValue |
---|
206 | if (!isDistributed) |
---|
207 | { |
---|
208 | // size = std::max(size, CArray<double,1>::size(n_glo) + (isCompressible_ ? CArray<int,1>::size(n_glo) : 0)); |
---|
209 | size += CArray<int,1>::size(n_glo); |
---|
210 | size += CArray<int,1>::size(n_glo); |
---|
211 | size += CArray<bool,1>::size(n_glo); |
---|
212 | size += CArray<double,1>::size(n_glo); |
---|
213 | if (hasBounds) |
---|
214 | size += CArray<double,2>::size(2*n_glo); |
---|
215 | if (hasLabel) |
---|
216 | size += CArray<StdString,1>::size(n_glo); |
---|
217 | } |
---|
218 | size += CEventClient::headerSize + getId().size() + sizeof(size_t); |
---|
219 | |
---|
220 | const std::list<int>& ranks = client->getRanksServerLeader(); |
---|
221 | for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) |
---|
222 | { |
---|
223 | if (size > attributesSizes[*itRank]) |
---|
224 | attributesSizes[*itRank] = size; |
---|
225 | } |
---|
226 | const std::list<int>& ranksNonLeaders = client->getRanksServerNotLeader(); |
---|
227 | for (std::list<int>::const_iterator itRank = ranksNonLeaders.begin(), itRankEnd = ranksNonLeaders.end(); itRank != itRankEnd; ++itRank) |
---|
228 | { |
---|
229 | if (size > attributesSizes[*itRank]) |
---|
230 | attributesSizes[*itRank] = size; |
---|
231 | } |
---|
232 | |
---|
233 | } |
---|
234 | |
---|
235 | if (isDistributed) |
---|
236 | { |
---|
237 | // size estimation for sendDistributedValue |
---|
238 | std::unordered_map<int, vector<size_t> >::const_iterator it, ite = indSrv_[client->serverSize].end(); |
---|
239 | for (it = indSrv_[client->serverSize].begin(); it != ite; ++it) |
---|
240 | { |
---|
241 | size_t size = 6 * sizeof(size_t); |
---|
242 | size += CArray<int,1>::size(it->second.size()); |
---|
243 | size += CArray<int,1>::size(it->second.size()); |
---|
244 | size += CArray<bool,1>::size(it->second.size()); |
---|
245 | size += CArray<double,1>::size(it->second.size()); |
---|
246 | if (hasBounds) |
---|
247 | size += CArray<double,2>::size(2 * it->second.size()); |
---|
248 | if (hasLabel) |
---|
249 | size += CArray<StdString,1>::size(it->second.size()); |
---|
250 | |
---|
251 | size += CEventClient::headerSize + getId().size() + sizeof(size_t); |
---|
252 | if (size > attributesSizes[it->first]) |
---|
253 | attributesSizes[it->first] = size; |
---|
254 | } |
---|
255 | } |
---|
256 | return attributesSizes; |
---|
257 | } |
---|
258 | CATCH_DUMP_ATTR |
---|
259 | |
---|
260 | //---------------------------------------------------------------- |
---|
261 | |
---|
262 | StdString CAxis::GetName(void) { return (StdString("axis")); } |
---|
263 | StdString CAxis::GetDefName(void){ return (CAxis::GetName()); } |
---|
264 | ENodeType CAxis::GetType(void) { return (eAxis); } |
---|
265 | |
---|
266 | //---------------------------------------------------------------- |
---|
267 | |
---|
268 | CAxis* CAxis::createAxis() |
---|
269 | TRY |
---|
270 | { |
---|
271 | CAxis* axis = CAxisGroup::get("axis_definition")->createChild(); |
---|
272 | return axis; |
---|
273 | } |
---|
274 | CATCH |
---|
275 | |
---|
276 | /*! |
---|
277 | Check common attributes of an axis. |
---|
278 | This check should be done in the very beginning of work flow |
---|
279 | */ |
---|
280 | void CAxis::checkAttributes(void) |
---|
281 | TRY |
---|
282 | { |
---|
283 | if (checkAttributes_done_) return ; |
---|
284 | |
---|
285 | CContext* context=CContext::getCurrent(); |
---|
286 | |
---|
287 | if (this->n_glo.isEmpty()) |
---|
288 | ERROR("CAxis::checkAttributes(void)", |
---|
289 | << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] " |
---|
290 | << "The axis is wrongly defined, attribute 'n_glo' must be specified"); |
---|
291 | StdSize size = this->n_glo.getValue(); |
---|
292 | |
---|
293 | if (!this->index.isEmpty()) |
---|
294 | { |
---|
295 | if (n.isEmpty()) n = index.numElements(); |
---|
296 | |
---|
297 | // It's not so correct but if begin is not the first value of index |
---|
298 | // then data on the local axis has user-defined distribution. In this case, begin has no meaning. |
---|
299 | if (begin.isEmpty()) begin = index(0); |
---|
300 | } |
---|
301 | else |
---|
302 | { |
---|
303 | if (!this->begin.isEmpty()) |
---|
304 | { |
---|
305 | if (begin < 0 || begin > size - 1) |
---|
306 | ERROR("CAxis::checkAttributes(void)", |
---|
307 | << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] " |
---|
308 | << "The axis is wrongly defined, attribute 'begin' (" << begin.getValue() << ") must be non-negative and smaller than size-1 (" << size - 1 << ")."); |
---|
309 | } |
---|
310 | else this->begin.setValue(0); |
---|
311 | |
---|
312 | if (!this->n.isEmpty()) |
---|
313 | { |
---|
314 | if (n < 0 || n > size) |
---|
315 | ERROR("CAxis::checkAttributes(void)", |
---|
316 | << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] " |
---|
317 | << "The axis is wrongly defined, attribute 'n' (" << n.getValue() << ") must be non-negative and smaller than size (" << size << ")."); |
---|
318 | } |
---|
319 | else this->n.setValue(size); |
---|
320 | |
---|
321 | { |
---|
322 | index.resize(n); |
---|
323 | for (int i = 0; i < n; ++i) index(i) = i+begin; |
---|
324 | } |
---|
325 | } |
---|
326 | |
---|
327 | if (!this->value.isEmpty()) |
---|
328 | { |
---|
329 | StdSize true_size = value.numElements(); |
---|
330 | if (this->n.getValue() != true_size) |
---|
331 | ERROR("CAxis::checkAttributes(void)", |
---|
332 | << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] " |
---|
333 | << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size |
---|
334 | << ") than the one defined by the \'size\' attribute (" << n.getValue() << ")."); |
---|
335 | this->hasValue = true; |
---|
336 | } |
---|
337 | |
---|
338 | this->checkBounds(); |
---|
339 | this->checkMask(); |
---|
340 | this->checkData(); |
---|
341 | this->checkLabel(); |
---|
342 | initializeLocalElement() ; |
---|
343 | addFullView() ; |
---|
344 | addWorkflowView() ; |
---|
345 | addModelView() ; |
---|
346 | |
---|
347 | checkAttributes_done_ = true ; |
---|
348 | } |
---|
349 | CATCH_DUMP_ATTR |
---|
350 | |
---|
351 | |
---|
352 | |
---|
353 | /*! |
---|
354 | Check the validity of data, fill in values if any, and apply mask. |
---|
355 | */ |
---|
356 | void CAxis::checkData() |
---|
357 | TRY |
---|
358 | { |
---|
359 | if (data_begin.isEmpty()) data_begin.setValue(0); |
---|
360 | |
---|
361 | if (data_n.isEmpty()) |
---|
362 | { |
---|
363 | data_n.setValue(n); |
---|
364 | } |
---|
365 | else if (data_n.getValue() < 0) |
---|
366 | { |
---|
367 | ERROR("CAxis::checkData(void)", |
---|
368 | << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] " |
---|
369 | << "The data size should be strictly positive ('data_n' = " << data_n.getValue() << ")."); |
---|
370 | } |
---|
371 | |
---|
372 | if (data_index.isEmpty()) |
---|
373 | { |
---|
374 | data_index.resize(data_n); |
---|
375 | for (int i = 0; i < data_n; ++i) |
---|
376 | { |
---|
377 | if ((i+data_begin) >= 0 && (i+data_begin<n)) |
---|
378 | { |
---|
379 | if (mask(i+data_begin)) |
---|
380 | data_index(i) = i+data_begin; |
---|
381 | else |
---|
382 | data_index(i) = -1; |
---|
383 | } |
---|
384 | else |
---|
385 | data_index(i) = -1; |
---|
386 | } |
---|
387 | } |
---|
388 | else |
---|
389 | { |
---|
390 | if (data_index.numElements() != data_n) |
---|
391 | { |
---|
392 | ERROR("CAxis::checkData(void)", |
---|
393 | << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] " |
---|
394 | << "The size of data_index = "<< data_index.numElements() << "is not equal to the data size data_n = " << data_n.getValue() << ")."); |
---|
395 | } |
---|
396 | for (int i = 0; i < data_n; ++i) |
---|
397 | { |
---|
398 | if (data_index(i) >= 0 && data_index(i)<n) |
---|
399 | if (!mask(data_index(i))) data_index(i) = -1; |
---|
400 | } |
---|
401 | } |
---|
402 | |
---|
403 | } |
---|
404 | CATCH_DUMP_ATTR |
---|
405 | |
---|
406 | size_t CAxis::getGlobalWrittenSize(void) |
---|
407 | { |
---|
408 | return n_glo ; |
---|
409 | } |
---|
410 | |
---|
411 | /*! |
---|
412 | Check validity of mask info and fill in values if any. |
---|
413 | */ |
---|
414 | void CAxis::checkMask() |
---|
415 | TRY |
---|
416 | { |
---|
417 | if (!mask.isEmpty()) |
---|
418 | { |
---|
419 | if (mask.extent(0) != n) |
---|
420 | { |
---|
421 | ERROR("CAxis::checkMask(void)", |
---|
422 | << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] " |
---|
423 | << "The mask does not have the same size as the local domain." << std::endl |
---|
424 | << "Local size is " << n.getValue() << "." << std::endl |
---|
425 | << "Mask size is " << mask.extent(0) << "."); |
---|
426 | } |
---|
427 | } |
---|
428 | else |
---|
429 | { |
---|
430 | mask.resize(n); |
---|
431 | mask = true; |
---|
432 | } |
---|
433 | } |
---|
434 | CATCH_DUMP_ATTR |
---|
435 | |
---|
436 | /*! |
---|
437 | Check validity of bounds info and fill in values if any. |
---|
438 | */ |
---|
439 | void CAxis::checkBounds() |
---|
440 | TRY |
---|
441 | { |
---|
442 | if (!bounds.isEmpty()) |
---|
443 | { |
---|
444 | if (bounds.extent(0) != 2 || bounds.extent(1) != n) |
---|
445 | ERROR("CAxis::checkAttributes(void)", |
---|
446 | << "The bounds array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension 2 x axis size." << std::endl |
---|
447 | << "Axis size is " << n.getValue() << "." << std::endl |
---|
448 | << "Bounds size is "<< bounds.extent(0) << " x " << bounds.extent(1) << "."); |
---|
449 | hasBounds = true; |
---|
450 | } |
---|
451 | else hasBounds = false; |
---|
452 | } |
---|
453 | CATCH_DUMP_ATTR |
---|
454 | |
---|
455 | void CAxis::checkLabel() |
---|
456 | TRY |
---|
457 | { |
---|
458 | if (!label.isEmpty()) |
---|
459 | { |
---|
460 | if (label.extent(0) != n) |
---|
461 | ERROR("CAxis::checkLabel(void)", |
---|
462 | << "The label array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension of axis size." << std::endl |
---|
463 | << "Axis size is " << n.getValue() << "." << std::endl |
---|
464 | << "label size is "<< label.extent(0)<< " ."); |
---|
465 | hasLabel = true; |
---|
466 | } |
---|
467 | else hasLabel = false; |
---|
468 | } |
---|
469 | CATCH_DUMP_ATTR |
---|
470 | |
---|
471 | |
---|
472 | /*! |
---|
473 | Dispatch event from the lower communication layer then process event according to its type |
---|
474 | */ |
---|
475 | bool CAxis::dispatchEvent(CEventServer& event) |
---|
476 | TRY |
---|
477 | { |
---|
478 | if (SuperClass::dispatchEvent(event)) return true; |
---|
479 | else |
---|
480 | { |
---|
481 | switch(event.type) |
---|
482 | { |
---|
483 | case EVENT_ID_DISTRIBUTION_ATTRIBUTE : |
---|
484 | recvDistributionAttribute(event); |
---|
485 | return true; |
---|
486 | break; |
---|
487 | case EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES: |
---|
488 | recvNonDistributedAttributes(event); |
---|
489 | return true; |
---|
490 | break; |
---|
491 | case EVENT_ID_DISTRIBUTED_ATTRIBUTES: |
---|
492 | recvDistributedAttributes_old(event); |
---|
493 | return true; |
---|
494 | break; |
---|
495 | case EVENT_ID_AXIS_DISTRIBUTION: |
---|
496 | recvAxisDistribution(event); |
---|
497 | return true; |
---|
498 | break; |
---|
499 | case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE: |
---|
500 | recvDistributedAttributes(event); |
---|
501 | return true; |
---|
502 | break; |
---|
503 | default : |
---|
504 | ERROR("bool CAxis::dispatchEvent(CEventServer& event)", |
---|
505 | << "Unknown Event"); |
---|
506 | return false; |
---|
507 | } |
---|
508 | } |
---|
509 | } |
---|
510 | CATCH |
---|
511 | |
---|
512 | /*! |
---|
513 | Check attributes on client side (This name is still adequate???) |
---|
514 | */ |
---|
515 | void CAxis::checkAttributesOnClient() |
---|
516 | TRY |
---|
517 | { |
---|
518 | if (this->areClientAttributesChecked_) return; |
---|
519 | |
---|
520 | CContext* context=CContext::getCurrent(); |
---|
521 | if (context->getServiceType()==CServicesManager::CLIENT) this->checkAttributes(); |
---|
522 | |
---|
523 | this->areClientAttributesChecked_ = true; |
---|
524 | } |
---|
525 | CATCH_DUMP_ATTR |
---|
526 | |
---|
527 | /* |
---|
528 | The (spatial) transformation sometimes can change attributes of an axis (e.g zoom can change mask or generate can change whole attributes) |
---|
529 | Therefore, we should recheck them. |
---|
530 | */ |
---|
531 | // ym : obsolete to be removed |
---|
532 | void CAxis::checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid, |
---|
533 | CServerDistributionDescription::ServerDistributionType distType) |
---|
534 | TRY |
---|
535 | { |
---|
536 | CContext* context=CContext::getCurrent() ; |
---|
537 | |
---|
538 | if (this->isClientAfterTransformationChecked) return; |
---|
539 | if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) |
---|
540 | { |
---|
541 | /* suppressed because of interface changed |
---|
542 | if (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType)) |
---|
543 | computeConnectedClients(globalDim, orderPositionInGrid, distType); |
---|
544 | else if (index.numElements() != n_glo) computeConnectedClients(globalDim, orderPositionInGrid, CServerDistributionDescription::ROOT_DISTRIBUTION); |
---|
545 | */ |
---|
546 | } |
---|
547 | |
---|
548 | this->isClientAfterTransformationChecked = true; |
---|
549 | } |
---|
550 | CATCH_DUMP_ATTR |
---|
551 | |
---|
552 | /* |
---|
553 | Send all checked attributes to server? (We dont have notion of server any more so client==server) |
---|
554 | \param [in] globalDim global dimension of grid containing this axis |
---|
555 | \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2) |
---|
556 | \param [in] distType distribution type of the server. For now, we only have band distribution. |
---|
557 | |
---|
558 | */ |
---|
559 | //ym obsolete : to be removed |
---|
560 | void CAxis::sendCheckedAttributes(const std::vector<int>& globalDim, int orderPositionInGrid, |
---|
561 | CServerDistributionDescription::ServerDistributionType distType) |
---|
562 | TRY |
---|
563 | { |
---|
564 | if (!this->areClientAttributesChecked_) checkAttributesOnClient(); |
---|
565 | if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation(globalDim, orderPositionInGrid, distType); |
---|
566 | CContext* context = CContext::getCurrent(); |
---|
567 | |
---|
568 | if (this->isChecked) return; |
---|
569 | if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) /*sendAttributes(globalDim, orderPositionInGrid, distType)*/; |
---|
570 | |
---|
571 | this->isChecked = true; |
---|
572 | } |
---|
573 | CATCH_DUMP_ATTR |
---|
574 | |
---|
575 | |
---|
576 | void CAxis::sendAxisToFileServer(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid) |
---|
577 | { |
---|
578 | if (sendAxisToFileServer_done_.count(client)!=0) return ; |
---|
579 | else sendAxisToFileServer_done_.insert(client) ; |
---|
580 | |
---|
581 | StdString axisDefRoot("axis_definition"); |
---|
582 | CAxisGroup* axisPtr = CAxisGroup::get(axisDefRoot); |
---|
583 | axisPtr->sendCreateChild(this->getId(),client); |
---|
584 | this->sendAllAttributesToServer(client) ; |
---|
585 | this->sendAttributes(client, globalDim, orderPositionInGrid, CServerDistributionDescription::BAND_DISTRIBUTION) ; |
---|
586 | } |
---|
587 | |
---|
588 | void CAxis::sendAxisToCouplerOut(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, const string& fieldId, int posInGrid) |
---|
589 | { |
---|
590 | if (sendAxisToFileServer_done_.count(client)!=0) return ; |
---|
591 | else sendAxisToFileServer_done_.insert(client) ; |
---|
592 | |
---|
593 | string axisId="_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ; |
---|
594 | |
---|
595 | if (!axis_ref.isEmpty()) |
---|
596 | { |
---|
597 | auto axis_ref_tmp=axis_ref.getValue() ; |
---|
598 | axis_ref.reset() ; // remove the reference, find an other way to do that more cleanly |
---|
599 | this->sendAllAttributesToServer(client, axisId) ; |
---|
600 | axis_ref = axis_ref_tmp ; |
---|
601 | } |
---|
602 | else this->sendAllAttributesToServer(client, axisId) ; |
---|
603 | |
---|
604 | this->sendAttributes(client, globalDim, orderPositionInGrid, CServerDistributionDescription::BAND_DISTRIBUTION, axisId) ; |
---|
605 | } |
---|
606 | |
---|
607 | void CAxis::makeAliasForCoupling(const string& fieldId, int posInGrid) |
---|
608 | { |
---|
609 | const string axisId = "_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ; |
---|
610 | this->createAlias(axisId) ; |
---|
611 | } |
---|
612 | |
---|
613 | /*! |
---|
614 | Send attributes from one client to other clients |
---|
615 | \param[in] globalDim global dimension of grid which contains this axis |
---|
616 | \param[in] order |
---|
617 | */ |
---|
618 | void CAxis::sendAttributes(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, |
---|
619 | CServerDistributionDescription::ServerDistributionType distType, const string& axisId) |
---|
620 | TRY |
---|
621 | { |
---|
622 | sendDistributionAttribute(client, globalDim, orderPositionInGrid, distType, axisId); |
---|
623 | |
---|
624 | // if (index.numElements() == n_glo.getValue()) |
---|
625 | if ((orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType)) |
---|
626 | || (index.numElements() != n_glo)) |
---|
627 | { |
---|
628 | sendDistributedAttributes_old(client, axisId); |
---|
629 | } |
---|
630 | else |
---|
631 | { |
---|
632 | sendNonDistributedAttributes(client, axisId); |
---|
633 | } |
---|
634 | } |
---|
635 | CATCH_DUMP_ATTR |
---|
636 | |
---|
637 | /* |
---|
638 | Compute the connection between group of clients (or clients/servers). |
---|
639 | (E.g: Suppose we have 2 group of clients in two model: A (client role) connect to B (server role), |
---|
640 | this function calculate number of clients B connect to one client of A) |
---|
641 | \param [in] globalDim global dimension of grid containing this axis |
---|
642 | \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2) |
---|
643 | \param [in] distType distribution type of the server. For now, we only have band distribution. |
---|
644 | */ |
---|
645 | void CAxis::computeConnectedClients(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid) |
---|
646 | TRY |
---|
647 | { |
---|
648 | if (computeConnectedClients_done_.count(client)!=0) return ; |
---|
649 | else computeConnectedClients_done_.insert(client) ; |
---|
650 | |
---|
651 | CContext* context = CContext::getCurrent(); |
---|
652 | CServerDistributionDescription::ServerDistributionType distType ; |
---|
653 | int defaultDistributedPos = CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), CServerDistributionDescription::BAND_DISTRIBUTION) ; |
---|
654 | |
---|
655 | if (orderPositionInGrid == defaultDistributedPos) distType = CServerDistributionDescription::BAND_DISTRIBUTION ; |
---|
656 | else if (index.numElements() != n_glo) distType = CServerDistributionDescription::ROOT_DISTRIBUTION ; |
---|
657 | else return ; |
---|
658 | |
---|
659 | int nbServer = client->serverSize; |
---|
660 | int range, clientSize = client->clientSize; |
---|
661 | int rank = client->clientRank; |
---|
662 | |
---|
663 | if (listNbServer_.count(nbServer) == 0) |
---|
664 | { |
---|
665 | listNbServer_.insert(nbServer) ; |
---|
666 | |
---|
667 | if (connectedServerRank_.find(nbServer) != connectedServerRank_.end()) |
---|
668 | { |
---|
669 | nbSenders.erase(nbServer); |
---|
670 | connectedServerRank_.erase(nbServer); |
---|
671 | } |
---|
672 | |
---|
673 | size_t ni = this->n.getValue(); |
---|
674 | size_t ibegin = this->begin.getValue(); |
---|
675 | size_t nbIndex = index.numElements(); |
---|
676 | |
---|
677 | // First of all, we should compute the mapping of the global index and local index of the current client |
---|
678 | if (globalLocalIndexMap_.empty()) |
---|
679 | { |
---|
680 | for (size_t idx = 0; idx < nbIndex; ++idx) |
---|
681 | { |
---|
682 | globalLocalIndexMap_[index(idx)] = idx; |
---|
683 | } |
---|
684 | } |
---|
685 | |
---|
686 | // Calculate the compressed index if any |
---|
687 | // std::set<int> writtenInd; |
---|
688 | // if (isCompressible_) |
---|
689 | // { |
---|
690 | // for (int idx = 0; idx < data_index.numElements(); ++idx) |
---|
691 | // { |
---|
692 | // int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni); |
---|
693 | // |
---|
694 | // if (ind >= 0 && ind < ni && mask(ind)) |
---|
695 | // { |
---|
696 | // ind += ibegin; |
---|
697 | // writtenInd.insert(ind); |
---|
698 | // } |
---|
699 | // } |
---|
700 | // } |
---|
701 | |
---|
702 | // Compute the global index of the current client (process) hold |
---|
703 | std::vector<int> nGlobAxis(1); |
---|
704 | nGlobAxis[0] = n_glo.getValue(); |
---|
705 | |
---|
706 | size_t globalSizeIndex = 1, indexBegin, indexEnd; |
---|
707 | for (int i = 0; i < nGlobAxis.size(); ++i) globalSizeIndex *= nGlobAxis[i]; |
---|
708 | indexBegin = 0; |
---|
709 | if (globalSizeIndex <= clientSize) |
---|
710 | { |
---|
711 | indexBegin = rank%globalSizeIndex; |
---|
712 | indexEnd = indexBegin; |
---|
713 | } |
---|
714 | else |
---|
715 | { |
---|
716 | for (int i = 0; i < clientSize; ++i) |
---|
717 | { |
---|
718 | range = globalSizeIndex / clientSize; |
---|
719 | if (i < (globalSizeIndex%clientSize)) ++range; |
---|
720 | if (i == client->clientRank) break; |
---|
721 | indexBegin += range; |
---|
722 | } |
---|
723 | indexEnd = indexBegin + range - 1; |
---|
724 | } |
---|
725 | |
---|
726 | CArray<size_t,1> globalIndex(index.numElements()); |
---|
727 | for (size_t idx = 0; idx < globalIndex.numElements(); ++idx) |
---|
728 | globalIndex(idx) = index(idx); |
---|
729 | |
---|
730 | // Describe the distribution of server side |
---|
731 | |
---|
732 | CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType); |
---|
733 | |
---|
734 | std::vector<int> serverZeroIndex; |
---|
735 | serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); |
---|
736 | |
---|
737 | std::list<int> serverZeroIndexLeader; |
---|
738 | std::list<int> serverZeroIndexNotLeader; |
---|
739 | CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); |
---|
740 | for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) |
---|
741 | *it = serverZeroIndex[*it]; |
---|
742 | |
---|
743 | // Find out the connection between client and server side |
---|
744 | CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); |
---|
745 | clientServerMap->computeServerIndexMapping(globalIndex, nbServer); |
---|
746 | CClientServerMapping::GlobalIndexMap& globalIndexAxisOnServer = clientServerMap->getGlobalIndexOnServer(); |
---|
747 | |
---|
748 | indSrv_[nbServer].swap(globalIndexAxisOnServer); |
---|
749 | |
---|
750 | if (distType==CServerDistributionDescription::ROOT_DISTRIBUTION) |
---|
751 | { |
---|
752 | for(int i=1; i<nbServer; ++i) indSrv_[nbServer].insert(pair<int, vector<size_t> >(i,indSrv_[nbServer][0]) ) ; |
---|
753 | serverZeroIndexLeader.clear() ; |
---|
754 | } |
---|
755 | |
---|
756 | CClientServerMapping::GlobalIndexMap::const_iterator it = indSrv_[nbServer].begin(), |
---|
757 | ite = indSrv_[nbServer].end(); |
---|
758 | |
---|
759 | for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first); |
---|
760 | |
---|
761 | for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) |
---|
762 | connectedServerRank_[nbServer].push_back(*it); |
---|
763 | |
---|
764 | // Even if a client has no index, it must connect to at least one server and |
---|
765 | // send an "empty" data to this server |
---|
766 | if (connectedServerRank_[nbServer].empty()) |
---|
767 | connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); |
---|
768 | |
---|
769 | nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); |
---|
770 | |
---|
771 | delete clientServerMap; |
---|
772 | } |
---|
773 | } |
---|
774 | CATCH_DUMP_ATTR |
---|
775 | |
---|
776 | /* |
---|
777 | Compute the index of data to write into file |
---|
778 | (Different from the previous version, this version of XIOS allows data be written into file (classical role), |
---|
779 | or transfered to another clients) |
---|
780 | */ |
---|
781 | void CAxis::computeWrittenIndex() |
---|
782 | TRY |
---|
783 | { |
---|
784 | if (computedWrittenIndex_) return; |
---|
785 | computedWrittenIndex_ = true; |
---|
786 | |
---|
787 | CContext* context=CContext::getCurrent(); |
---|
788 | |
---|
789 | // We describe the distribution of client (server) on which data are written |
---|
790 | std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1); |
---|
791 | nBegin[0] = begin; |
---|
792 | nSize[0] = n; |
---|
793 | nBeginGlobal[0] = 0; |
---|
794 | nGlob[0] = n_glo; |
---|
795 | CDistributionServer srvDist(context->intraCommSize_, nBegin, nSize, nBeginGlobal, nGlob); |
---|
796 | const CArray<size_t,1>& writtenGlobalIndex = srvDist.getGlobalIndex(); |
---|
797 | |
---|
798 | // Because all written data are local on a client, |
---|
799 | // we need to compute the local index on the server from its corresponding global index |
---|
800 | size_t nbWritten = 0, indGlo; |
---|
801 | std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(), |
---|
802 | ite = globalLocalIndexMap_.end(), it; |
---|
803 | CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(), |
---|
804 | itSrve = writtenGlobalIndex.end(), itSrv; |
---|
805 | |
---|
806 | localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements()); |
---|
807 | nbWritten = 0; |
---|
808 | for (itSrv = itSrvb; itSrv != itSrve; ++itSrv) |
---|
809 | { |
---|
810 | indGlo = *itSrv; |
---|
811 | if (ite != globalLocalIndexMap_.find(indGlo)) |
---|
812 | { |
---|
813 | localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo]; |
---|
814 | } |
---|
815 | else |
---|
816 | { |
---|
817 | localIndexToWriteOnServer(nbWritten) = -1; |
---|
818 | } |
---|
819 | ++nbWritten; |
---|
820 | } |
---|
821 | |
---|
822 | } |
---|
823 | CATCH_DUMP_ATTR |
---|
824 | |
---|
825 | void CAxis::computeWrittenCompressedIndex(MPI_Comm writtenComm) |
---|
826 | TRY |
---|
827 | { |
---|
828 | int writtenCommSize; |
---|
829 | MPI_Comm_size(writtenComm, &writtenCommSize); |
---|
830 | if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end()) |
---|
831 | return; |
---|
832 | |
---|
833 | if (isCompressible()) |
---|
834 | { |
---|
835 | size_t nbWritten = 0, indGlo; |
---|
836 | CContext* context=CContext::getCurrent(); |
---|
837 | |
---|
838 | // We describe the distribution of client (server) on which data are written |
---|
839 | std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1); |
---|
840 | nBegin[0] = 0; |
---|
841 | nSize[0] = n; |
---|
842 | nBeginGlobal[0] = 0; |
---|
843 | nGlob[0] = n_glo; |
---|
844 | CDistributionServer srvDist(context->intraCommSize_, nBegin, nSize, nBeginGlobal, nGlob); |
---|
845 | const CArray<size_t,1>& writtenGlobalIndex = srvDist.getGlobalIndex(); |
---|
846 | std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(), |
---|
847 | ite = globalLocalIndexMap_.end(), it; |
---|
848 | |
---|
849 | CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(), |
---|
850 | itSrve = writtenGlobalIndex.end(), itSrv; |
---|
851 | std::unordered_map<size_t,size_t> localGlobalIndexMap; |
---|
852 | for (itSrv = itSrvb; itSrv != itSrve; ++itSrv) |
---|
853 | { |
---|
854 | indGlo = *itSrv; |
---|
855 | if (ite != globalLocalIndexMap_.find(indGlo)) |
---|
856 | { |
---|
857 | localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo; |
---|
858 | ++nbWritten; |
---|
859 | } |
---|
860 | } |
---|
861 | // |
---|
862 | // nbWritten = 0; |
---|
863 | // for (int idx = 0; idx < data_index.numElements(); ++idx) |
---|
864 | // { |
---|
865 | // if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx))) |
---|
866 | // { |
---|
867 | // ++nbWritten; |
---|
868 | // } |
---|
869 | // } |
---|
870 | // |
---|
871 | // compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten); |
---|
872 | // nbWritten = 0; |
---|
873 | // for (int idx = 0; idx < data_index.numElements(); ++idx) |
---|
874 | // { |
---|
875 | // if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx))) |
---|
876 | // { |
---|
877 | // compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)]; |
---|
878 | // ++nbWritten; |
---|
879 | // } |
---|
880 | // } |
---|
881 | |
---|
882 | nbWritten = 0; |
---|
883 | for (int idx = 0; idx < data_index.numElements(); ++idx) |
---|
884 | { |
---|
885 | if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx))) |
---|
886 | { |
---|
887 | ++nbWritten; |
---|
888 | } |
---|
889 | } |
---|
890 | |
---|
891 | compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten); |
---|
892 | nbWritten = 0; |
---|
893 | for (int idx = 0; idx < data_index.numElements(); ++idx) |
---|
894 | { |
---|
895 | if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx))) |
---|
896 | { |
---|
897 | compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)]; |
---|
898 | ++nbWritten; |
---|
899 | } |
---|
900 | } |
---|
901 | |
---|
902 | numberWrittenIndexes_[writtenCommSize] = nbWritten; |
---|
903 | |
---|
904 | bool distributed_glo, distributed=isDistributed() ; |
---|
905 | MPI_Allreduce(&distributed,&distributed_glo, 1, MPI_INT, MPI_LOR, writtenComm) ; |
---|
906 | if (distributed_glo) |
---|
907 | { |
---|
908 | |
---|
909 | MPI_Allreduce(&numberWrittenIndexes_[writtenCommSize], &totalNumberWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm); |
---|
910 | MPI_Scan(&numberWrittenIndexes_[writtenCommSize], &offsetWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm); |
---|
911 | offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize]; |
---|
912 | } |
---|
913 | else |
---|
914 | totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize]; |
---|
915 | } |
---|
916 | } |
---|
917 | CATCH_DUMP_ATTR |
---|
918 | |
---|
919 | /*! |
---|
920 | Send distribution information from a group of client (client role) to another group of client (server role) |
---|
921 | The distribution of a group of client (server role) is imposed by the group of client (client role) |
---|
922 | \param [in] globalDim global dimension of grid containing this axis |
---|
923 | \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2) |
---|
924 | \param [in] distType distribution type of the server. For now, we only have band distribution. |
---|
925 | */ |
---|
926 | void CAxis::sendDistributionAttribute(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, |
---|
927 | CServerDistributionDescription::ServerDistributionType distType, const string& axisId) |
---|
928 | TRY |
---|
929 | { |
---|
930 | string serverAxisId = axisId.empty() ? this->getId() : axisId ; |
---|
931 | int nbServer = client->serverSize; |
---|
932 | |
---|
933 | CServerDistributionDescription serverDescription(globalDim, nbServer); |
---|
934 | serverDescription.computeServerDistribution(); |
---|
935 | |
---|
936 | std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin(); |
---|
937 | std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes(); |
---|
938 | |
---|
939 | CEventClient event(getType(),EVENT_ID_DISTRIBUTION_ATTRIBUTE); |
---|
940 | if (client->isServerLeader()) |
---|
941 | { |
---|
942 | std::list<CMessage> msgs; |
---|
943 | |
---|
944 | const std::list<int>& ranks = client->getRanksServerLeader(); |
---|
945 | for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) |
---|
946 | { |
---|
947 | // Use const int to ensure CMessage holds a copy of the value instead of just a reference |
---|
948 | const int begin = serverIndexBegin[*itRank][orderPositionInGrid]; |
---|
949 | const int ni = serverDimensionSizes[*itRank][orderPositionInGrid]; |
---|
950 | |
---|
951 | msgs.push_back(CMessage()); |
---|
952 | CMessage& msg = msgs.back(); |
---|
953 | msg << serverAxisId; |
---|
954 | msg << ni << begin; |
---|
955 | msg << isCompressible_; |
---|
956 | |
---|
957 | event.push(*itRank,1,msg); |
---|
958 | } |
---|
959 | client->sendEvent(event); |
---|
960 | } |
---|
961 | else client->sendEvent(event); |
---|
962 | } |
---|
963 | CATCH_DUMP_ATTR |
---|
964 | |
---|
965 | /* |
---|
966 | Receive distribution attribute from another client |
---|
967 | \param [in] event event containing data of these attributes |
---|
968 | */ |
---|
969 | void CAxis::recvDistributionAttribute(CEventServer& event) |
---|
970 | TRY |
---|
971 | { |
---|
972 | CBufferIn* buffer = event.subEvents.begin()->buffer; |
---|
973 | string axisId; |
---|
974 | *buffer >> axisId; |
---|
975 | get(axisId)->recvDistributionAttribute(*buffer); |
---|
976 | } |
---|
977 | CATCH |
---|
978 | |
---|
979 | /* |
---|
980 | Receive distribution attribute from another client |
---|
981 | \param [in] buffer buffer containing data of these attributes |
---|
982 | */ |
---|
983 | void CAxis::recvDistributionAttribute(CBufferIn& buffer) |
---|
984 | TRY |
---|
985 | { |
---|
986 | int ni_srv, begin_srv; |
---|
987 | buffer >> ni_srv >> begin_srv; |
---|
988 | buffer >> isCompressible_; |
---|
989 | |
---|
990 | // Set up new local size of axis on the receiving clients |
---|
991 | n.setValue(ni_srv); |
---|
992 | begin.setValue(begin_srv); |
---|
993 | } |
---|
994 | CATCH_DUMP_ATTR |
---|
995 | |
---|
996 | /* |
---|
997 | Send attributes of axis from a group of client to other group of clients/servers |
---|
998 | on supposing that these attributes are not distributed among the sending group |
---|
999 | In the future, if new attributes are added, they should also be processed in this function |
---|
1000 | */ |
---|
1001 | void CAxis::sendNonDistributedAttributes(CContextClient* client, const string& axisId) |
---|
1002 | TRY |
---|
1003 | { |
---|
1004 | string serverAxisId = axisId.empty() ? this->getId() : axisId ; |
---|
1005 | |
---|
1006 | CEventClient event(getType(), EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES); |
---|
1007 | size_t nbIndex = index.numElements(); |
---|
1008 | size_t nbDataIndex = 0; |
---|
1009 | |
---|
1010 | for (int idx = 0; idx < data_index.numElements(); ++idx) |
---|
1011 | { |
---|
1012 | int ind = data_index(idx); |
---|
1013 | if (ind >= 0 && ind < nbIndex) ++nbDataIndex; |
---|
1014 | } |
---|
1015 | |
---|
1016 | CArray<int,1> dataIndex(nbDataIndex); |
---|
1017 | nbDataIndex = 0; |
---|
1018 | for (int idx = 0; idx < data_index.numElements(); ++idx) |
---|
1019 | { |
---|
1020 | int ind = data_index(idx); |
---|
1021 | if (ind >= 0 && ind < nbIndex) |
---|
1022 | { |
---|
1023 | dataIndex(nbDataIndex) = ind; |
---|
1024 | ++nbDataIndex; |
---|
1025 | } |
---|
1026 | } |
---|
1027 | |
---|
1028 | if (client->isServerLeader()) |
---|
1029 | { |
---|
1030 | std::list<CMessage> msgs; |
---|
1031 | |
---|
1032 | const std::list<int>& ranks = client->getRanksServerLeader(); |
---|
1033 | for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) |
---|
1034 | { |
---|
1035 | msgs.push_back(CMessage()); |
---|
1036 | CMessage& msg = msgs.back(); |
---|
1037 | msg << serverAxisId; |
---|
1038 | msg << index.getValue() << dataIndex << mask.getValue(); |
---|
1039 | msg << hasValue; |
---|
1040 | if (hasValue) msg << value.getValue(); |
---|
1041 | msg << hasBounds; |
---|
1042 | if (hasBounds) msg << bounds.getValue(); |
---|
1043 | msg << hasLabel; |
---|
1044 | if (hasLabel) msg << label.getValue(); |
---|
1045 | |
---|
1046 | event.push(*itRank, 1, msg); |
---|
1047 | } |
---|
1048 | client->sendEvent(event); |
---|
1049 | } |
---|
1050 | else client->sendEvent(event); |
---|
1051 | } |
---|
1052 | CATCH_DUMP_ATTR |
---|
1053 | |
---|
1054 | /* |
---|
1055 | Receive the non-distributed attributes from another group of clients |
---|
1056 | \param [in] event event containing data of these attributes |
---|
1057 | */ |
---|
1058 | void CAxis::recvNonDistributedAttributes(CEventServer& event) |
---|
1059 | TRY |
---|
1060 | { |
---|
1061 | list<CEventServer::SSubEvent>::iterator it; |
---|
1062 | for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) |
---|
1063 | { |
---|
1064 | CBufferIn* buffer = it->buffer; |
---|
1065 | string axisId; |
---|
1066 | *buffer >> axisId; |
---|
1067 | get(axisId)->recvNonDistributedAttributes(it->rank, *buffer); |
---|
1068 | } |
---|
1069 | } |
---|
1070 | CATCH |
---|
1071 | |
---|
1072 | /* |
---|
1073 | Receive the non-distributed attributes from another group of clients |
---|
1074 | \param [in] rank rank of the sender |
---|
1075 | \param [in] buffer buffer containing data sent from the sender |
---|
1076 | */ |
---|
1077 | void CAxis::recvNonDistributedAttributes(int rank, CBufferIn& buffer) |
---|
1078 | TRY |
---|
1079 | { |
---|
1080 | CArray<int,1> tmp_index, tmp_data_index; |
---|
1081 | CArray<bool,1> tmp_mask; |
---|
1082 | CArray<double,1> tmp_val; |
---|
1083 | CArray<double,2> tmp_bnds; |
---|
1084 | CArray<string,1> tmp_label; |
---|
1085 | |
---|
1086 | buffer >> tmp_index; |
---|
1087 | index.reference(tmp_index); |
---|
1088 | buffer >> tmp_data_index; |
---|
1089 | data_index.reference(tmp_data_index); |
---|
1090 | buffer >> tmp_mask; |
---|
1091 | mask.reference(tmp_mask); |
---|
1092 | |
---|
1093 | buffer >> hasValue; |
---|
1094 | if (hasValue) |
---|
1095 | { |
---|
1096 | buffer >> tmp_val; |
---|
1097 | value.reference(tmp_val); |
---|
1098 | } |
---|
1099 | |
---|
1100 | buffer >> hasBounds; |
---|
1101 | if (hasBounds) |
---|
1102 | { |
---|
1103 | buffer >> tmp_bnds; |
---|
1104 | bounds.reference(tmp_bnds); |
---|
1105 | } |
---|
1106 | |
---|
1107 | buffer >> hasLabel; |
---|
1108 | if (hasLabel) |
---|
1109 | { |
---|
1110 | buffer >> tmp_label; |
---|
1111 | label.reference(tmp_label); |
---|
1112 | } |
---|
1113 | |
---|
1114 | // Some value should be reset here |
---|
1115 | data_begin.setValue(0); |
---|
1116 | data_n.setValue(data_index.numElements()); |
---|
1117 | globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor())); |
---|
1118 | // for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[idx] = index(idx); |
---|
1119 | for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[index(idx)] = idx; |
---|
1120 | } |
---|
1121 | CATCH_DUMP_ATTR |
---|
1122 | |
---|
1123 | /* |
---|
1124 | Send axis attributes from a group of clients to another group of clients/servers |
---|
1125 | supposing that these attributes are distributed among the clients of the sending group |
---|
1126 | In future, if new attributes are added, they should also be processed in this function |
---|
1127 | */ |
---|
1128 | void CAxis::sendDistributedAttributes_old(CContextClient* client, const string& axisId) |
---|
1129 | TRY |
---|
1130 | { |
---|
1131 | string serverAxisId = axisId.empty() ? this->getId() : axisId ; |
---|
1132 | |
---|
1133 | int ind, idx; |
---|
1134 | int nbServer = client->serverSize; |
---|
1135 | |
---|
1136 | CEventClient eventData(getType(), EVENT_ID_DISTRIBUTED_ATTRIBUTES); |
---|
1137 | |
---|
1138 | list<CMessage> listData; |
---|
1139 | list<CArray<int,1> > list_indi, list_dataInd; |
---|
1140 | list<CArray<double,1> > list_val; |
---|
1141 | list<CArray<double,2> > list_bounds; |
---|
1142 | list<CArray<string,1> > list_label; |
---|
1143 | |
---|
1144 | // Cut off the ghost points |
---|
1145 | int nbIndex = index.numElements(); |
---|
1146 | CArray<int,1> dataIndex(nbIndex); |
---|
1147 | dataIndex = -1; |
---|
1148 | for (idx = 0; idx < data_index.numElements(); ++idx) |
---|
1149 | { |
---|
1150 | if (0 <= data_index(idx) && data_index(idx) < nbIndex) |
---|
1151 | dataIndex(data_index(idx)) = 1; |
---|
1152 | } |
---|
1153 | |
---|
1154 | std::unordered_map<int, std::vector<size_t> >::const_iterator it, iteMap; |
---|
1155 | iteMap = indSrv_[nbServer].end(); |
---|
1156 | for (int k = 0; k < connectedServerRank_[nbServer].size(); ++k) |
---|
1157 | { |
---|
1158 | int nbData = 0, nbDataCount = 0; |
---|
1159 | int rank = connectedServerRank_[nbServer][k]; |
---|
1160 | it = indSrv_[nbServer].find(rank); |
---|
1161 | if (iteMap != it) |
---|
1162 | nbData = it->second.size(); |
---|
1163 | |
---|
1164 | list_indi.push_back(CArray<int,1>(nbData)); |
---|
1165 | list_dataInd.push_back(CArray<int,1>(nbData)); |
---|
1166 | |
---|
1167 | if (hasValue) |
---|
1168 | list_val.push_back(CArray<double,1>(nbData)); |
---|
1169 | |
---|
1170 | if (hasBounds) |
---|
1171 | list_bounds.push_back(CArray<double,2>(2,nbData)); |
---|
1172 | |
---|
1173 | if (hasLabel) |
---|
1174 | list_label.push_back(CArray<string,1>(nbData)); |
---|
1175 | |
---|
1176 | CArray<int,1>& indi = list_indi.back(); |
---|
1177 | CArray<int,1>& dataIndi = list_dataInd.back(); |
---|
1178 | dataIndi = -1; |
---|
1179 | |
---|
1180 | for (int n = 0; n < nbData; ++n) |
---|
1181 | { |
---|
1182 | idx = static_cast<int>(it->second[n]); |
---|
1183 | indi(n) = idx; |
---|
1184 | |
---|
1185 | ind = globalLocalIndexMap_[idx]; |
---|
1186 | dataIndi(n) = dataIndex(ind); |
---|
1187 | |
---|
1188 | if (hasValue) |
---|
1189 | { |
---|
1190 | CArray<double,1>& val = list_val.back(); |
---|
1191 | val(n) = value(ind); |
---|
1192 | } |
---|
1193 | |
---|
1194 | if (hasBounds) |
---|
1195 | { |
---|
1196 | CArray<double,2>& boundsVal = list_bounds.back(); |
---|
1197 | boundsVal(0, n) = bounds(0,ind); |
---|
1198 | boundsVal(1, n) = bounds(1,ind); |
---|
1199 | } |
---|
1200 | |
---|
1201 | if (hasLabel) |
---|
1202 | { |
---|
1203 | CArray<string,1>& labelVal = list_label.back(); |
---|
1204 | labelVal(n) = label(ind); |
---|
1205 | } |
---|
1206 | } |
---|
1207 | |
---|
1208 | listData.push_back(CMessage()); |
---|
1209 | listData.back() << serverAxisId |
---|
1210 | << list_indi.back() << list_dataInd.back(); |
---|
1211 | |
---|
1212 | listData.back() << hasValue; |
---|
1213 | if (hasValue) |
---|
1214 | listData.back() << list_val.back(); |
---|
1215 | |
---|
1216 | listData.back() << hasBounds; |
---|
1217 | if (hasBounds) |
---|
1218 | listData.back() << list_bounds.back(); |
---|
1219 | |
---|
1220 | listData.back() << hasLabel; |
---|
1221 | if (hasLabel) |
---|
1222 | listData.back() << list_label.back(); |
---|
1223 | |
---|
1224 | eventData.push(rank, nbSenders[nbServer][rank], listData.back()); |
---|
1225 | } |
---|
1226 | |
---|
1227 | client->sendEvent(eventData); |
---|
1228 | } |
---|
1229 | CATCH_DUMP_ATTR |
---|
1230 | |
---|
1231 | /* |
---|
1232 | Receive the distributed attributes from another group of clients |
---|
1233 | \param [in] event event containing data of these attributes |
---|
1234 | */ |
---|
1235 | void CAxis::recvDistributedAttributes_old(CEventServer& event) |
---|
1236 | TRY |
---|
1237 | { |
---|
1238 | string axisId; |
---|
1239 | vector<int> ranks; |
---|
1240 | vector<CBufferIn*> buffers; |
---|
1241 | |
---|
1242 | list<CEventServer::SSubEvent>::iterator it; |
---|
1243 | for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) |
---|
1244 | { |
---|
1245 | ranks.push_back(it->rank); |
---|
1246 | CBufferIn* buffer = it->buffer; |
---|
1247 | *buffer >> axisId; |
---|
1248 | buffers.push_back(buffer); |
---|
1249 | } |
---|
1250 | get(axisId)->recvDistributedAttributes_old(ranks, buffers); |
---|
1251 | } |
---|
1252 | CATCH |
---|
1253 | |
---|
1254 | /* |
---|
1255 | Receive the non-distributed attributes from another group of clients |
---|
1256 | \param [in] ranks rank of the sender |
---|
1257 | \param [in] buffers buffer containing data sent from the sender |
---|
1258 | */ |
---|
1259 | void CAxis::recvDistributedAttributes_old(vector<int>& ranks, vector<CBufferIn*> buffers) |
---|
1260 | TRY |
---|
1261 | { |
---|
1262 | int nbReceived = ranks.size(), idx, ind, gloInd, locInd; |
---|
1263 | vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived); |
---|
1264 | vector<CArray<double,1> > vec_val(nbReceived); |
---|
1265 | vector<CArray<double,2> > vec_bounds(nbReceived); |
---|
1266 | vector<CArray<string,1> > vec_label(nbReceived); |
---|
1267 | |
---|
1268 | for (idx = 0; idx < nbReceived; ++idx) |
---|
1269 | { |
---|
1270 | CBufferIn& buffer = *buffers[idx]; |
---|
1271 | buffer >> vec_indi[idx]; |
---|
1272 | buffer >> vec_dataInd[idx]; |
---|
1273 | |
---|
1274 | buffer >> hasValue; |
---|
1275 | if (hasValue) |
---|
1276 | buffer >> vec_val[idx]; |
---|
1277 | |
---|
1278 | buffer >> hasBounds; |
---|
1279 | if (hasBounds) |
---|
1280 | buffer >> vec_bounds[idx]; |
---|
1281 | |
---|
1282 | buffer >> hasLabel; |
---|
1283 | if (hasLabel) |
---|
1284 | buffer >> vec_label[idx]; |
---|
1285 | } |
---|
1286 | |
---|
1287 | // Estimate size of index array |
---|
1288 | int nbIndexGlob = 0; |
---|
1289 | for (idx = 0; idx < nbReceived; ++idx) |
---|
1290 | { |
---|
1291 | nbIndexGlob += vec_indi[idx].numElements(); |
---|
1292 | } |
---|
1293 | |
---|
1294 | // Recompute global index |
---|
1295 | // Take account of the overlapped index |
---|
1296 | index.resize(nbIndexGlob); |
---|
1297 | globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor())); |
---|
1298 | nbIndexGlob = 0; |
---|
1299 | int nbIndLoc = 0; |
---|
1300 | for (idx = 0; idx < nbReceived; ++idx) |
---|
1301 | { |
---|
1302 | CArray<int,1>& tmp = vec_indi[idx]; |
---|
1303 | for (ind = 0; ind < tmp.numElements(); ++ind) |
---|
1304 | { |
---|
1305 | gloInd = tmp(ind); |
---|
1306 | nbIndLoc = (gloInd % n_glo)-begin; |
---|
1307 | if (0 == globalLocalIndexMap_.count(gloInd)) |
---|
1308 | { |
---|
1309 | index(nbIndexGlob) = gloInd % n_glo; |
---|
1310 | globalLocalIndexMap_[gloInd] = nbIndexGlob; |
---|
1311 | ++nbIndexGlob; |
---|
1312 | } |
---|
1313 | } |
---|
1314 | } |
---|
1315 | |
---|
1316 | // Resize index to its real size |
---|
1317 | if (nbIndexGlob==0) index.resize(nbIndexGlob) ; |
---|
1318 | else index.resizeAndPreserve(nbIndexGlob); |
---|
1319 | |
---|
1320 | int nbData = nbIndexGlob; |
---|
1321 | CArray<int,1> nonCompressedData(nbData); |
---|
1322 | nonCompressedData = -1; |
---|
1323 | // Mask is incorporated into data_index and is not sent/received anymore |
---|
1324 | mask.reset(); |
---|
1325 | if (hasValue) |
---|
1326 | value.resize(nbData); |
---|
1327 | if (hasBounds) |
---|
1328 | bounds.resize(2,nbData); |
---|
1329 | if (hasLabel) |
---|
1330 | label.resize(nbData); |
---|
1331 | |
---|
1332 | nbData = 0; |
---|
1333 | for (idx = 0; idx < nbReceived; ++idx) |
---|
1334 | { |
---|
1335 | CArray<int,1>& indi = vec_indi[idx]; |
---|
1336 | CArray<int,1>& dataIndi = vec_dataInd[idx]; |
---|
1337 | int nb = indi.numElements(); |
---|
1338 | for (int n = 0; n < nb; ++n) |
---|
1339 | { |
---|
1340 | locInd = globalLocalIndexMap_[size_t(indi(n))]; |
---|
1341 | |
---|
1342 | nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd); |
---|
1343 | |
---|
1344 | if (hasValue) |
---|
1345 | value(locInd) = vec_val[idx](n); |
---|
1346 | |
---|
1347 | if (hasBounds) |
---|
1348 | { |
---|
1349 | bounds(0,locInd) = vec_bounds[idx](0,n); |
---|
1350 | bounds(1,locInd) = vec_bounds[idx](1,n); |
---|
1351 | } |
---|
1352 | |
---|
1353 | if (hasLabel) |
---|
1354 | label(locInd) = vec_label[idx](n); |
---|
1355 | } |
---|
1356 | } |
---|
1357 | |
---|
1358 | int nbCompressedData = 0; |
---|
1359 | for (idx = 0; idx < nonCompressedData.numElements(); ++idx) |
---|
1360 | { |
---|
1361 | if (0 <= nonCompressedData(idx)) |
---|
1362 | ++nbCompressedData; |
---|
1363 | } |
---|
1364 | |
---|
1365 | data_index.resize(nbCompressedData); |
---|
1366 | nbCompressedData = 0; |
---|
1367 | for (idx = 0; idx < nonCompressedData.numElements(); ++idx) |
---|
1368 | { |
---|
1369 | if (0 <= nonCompressedData(idx)) |
---|
1370 | { |
---|
1371 | data_index(nbCompressedData) = idx % n; |
---|
1372 | ++nbCompressedData; |
---|
1373 | } |
---|
1374 | } |
---|
1375 | |
---|
1376 | data_begin.setValue(0); |
---|
1377 | data_n.setValue(data_index.numElements()); |
---|
1378 | } |
---|
1379 | CATCH_DUMP_ATTR |
---|
1380 | |
---|
1381 | /*! |
---|
1382 | Compare two axis objects. |
---|
1383 | They are equal if only if they have identical attributes as well as their values. |
---|
1384 | Moreover, they must have the same transformations. |
---|
1385 | \param [in] axis Compared axis |
---|
1386 | \return result of the comparison |
---|
1387 | */ |
---|
1388 | bool CAxis::isEqual(CAxis* obj) |
---|
1389 | TRY |
---|
1390 | { |
---|
1391 | vector<StdString> excludedAttr; |
---|
1392 | excludedAttr.push_back("axis_ref"); |
---|
1393 | |
---|
1394 | bool objEqual = SuperClass::isEqual(obj, excludedAttr); |
---|
1395 | if (!objEqual) return objEqual; |
---|
1396 | |
---|
1397 | TransMapTypes thisTrans = this->getAllTransformations(); |
---|
1398 | TransMapTypes objTrans = obj->getAllTransformations(); |
---|
1399 | |
---|
1400 | TransMapTypes::const_iterator it, itb, ite; |
---|
1401 | std::vector<ETranformationType> thisTransType, objTransType; |
---|
1402 | for (it = thisTrans.begin(); it != thisTrans.end(); ++it) |
---|
1403 | thisTransType.push_back(it->first); |
---|
1404 | for (it = objTrans.begin(); it != objTrans.end(); ++it) |
---|
1405 | objTransType.push_back(it->first); |
---|
1406 | |
---|
1407 | if (thisTransType.size() != objTransType.size()) return false; |
---|
1408 | for (int idx = 0; idx < thisTransType.size(); ++idx) |
---|
1409 | objEqual &= (thisTransType[idx] == objTransType[idx]); |
---|
1410 | |
---|
1411 | return objEqual; |
---|
1412 | } |
---|
1413 | CATCH_DUMP_ATTR |
---|
1414 | |
---|
1415 | /* |
---|
1416 | Add transformation into axis. This function only servers for Fortran interface |
---|
1417 | \param [in] transType transformation type |
---|
1418 | \param [in] id identifier of the transformation object |
---|
1419 | */ |
---|
1420 | CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id) |
---|
1421 | TRY |
---|
1422 | { |
---|
1423 | transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id))); |
---|
1424 | return transformationMap_.back().second; |
---|
1425 | } |
---|
1426 | CATCH_DUMP_ATTR |
---|
1427 | |
---|
1428 | /* |
---|
1429 | Check whether an axis has (spatial) transformation |
---|
1430 | */ |
---|
1431 | bool CAxis::hasTransformation() |
---|
1432 | TRY |
---|
1433 | { |
---|
1434 | return (!transformationMap_.empty()); |
---|
1435 | } |
---|
1436 | CATCH_DUMP_ATTR |
---|
1437 | |
---|
1438 | /* |
---|
1439 | Set transformation |
---|
1440 | \param [in] axisTrans transformation to set |
---|
1441 | */ |
---|
1442 | void CAxis::setTransformations(const TransMapTypes& axisTrans) |
---|
1443 | TRY |
---|
1444 | { |
---|
1445 | transformationMap_ = axisTrans; |
---|
1446 | } |
---|
1447 | CATCH_DUMP_ATTR |
---|
1448 | |
---|
1449 | /* |
---|
1450 | Return all transformation held by the axis |
---|
1451 | \return transformation the axis has |
---|
1452 | */ |
---|
1453 | CAxis::TransMapTypes CAxis::getAllTransformations(void) |
---|
1454 | TRY |
---|
1455 | { |
---|
1456 | return transformationMap_; |
---|
1457 | } |
---|
1458 | CATCH_DUMP_ATTR |
---|
1459 | |
---|
1460 | /* |
---|
1461 | Duplicate transformation of another axis |
---|
1462 | \param [in] src axis whose transformations are copied |
---|
1463 | */ |
---|
1464 | void CAxis::duplicateTransformation(CAxis* src) |
---|
1465 | TRY |
---|
1466 | { |
---|
1467 | if (src->hasTransformation()) |
---|
1468 | { |
---|
1469 | this->setTransformations(src->getAllTransformations()); |
---|
1470 | } |
---|
1471 | } |
---|
1472 | CATCH_DUMP_ATTR |
---|
1473 | |
---|
1474 | /*! |
---|
1475 | * Go through the hierarchy to find the axis from which the transformations must be inherited |
---|
1476 | */ |
---|
1477 | void CAxis::solveInheritanceTransformation() |
---|
1478 | TRY |
---|
1479 | { |
---|
1480 | if (hasTransformation() || !hasDirectAxisReference()) |
---|
1481 | return; |
---|
1482 | |
---|
1483 | CAxis* axis = this; |
---|
1484 | std::vector<CAxis*> refAxis; |
---|
1485 | while (!axis->hasTransformation() && axis->hasDirectAxisReference()) |
---|
1486 | { |
---|
1487 | refAxis.push_back(axis); |
---|
1488 | axis = axis->getDirectAxisReference(); |
---|
1489 | } |
---|
1490 | |
---|
1491 | if (axis->hasTransformation()) |
---|
1492 | for (size_t i = 0; i < refAxis.size(); ++i) |
---|
1493 | refAxis[i]->setTransformations(axis->getAllTransformations()); |
---|
1494 | } |
---|
1495 | CATCH_DUMP_ATTR |
---|
1496 | |
---|
1497 | void CAxis::setContextClient(CContextClient* contextClient) |
---|
1498 | TRY |
---|
1499 | { |
---|
1500 | if (clientsSet.find(contextClient)==clientsSet.end()) |
---|
1501 | { |
---|
1502 | clients.push_back(contextClient) ; |
---|
1503 | clientsSet.insert(contextClient); |
---|
1504 | } |
---|
1505 | } |
---|
1506 | CATCH_DUMP_ATTR |
---|
1507 | |
---|
1508 | void CAxis::parse(xml::CXMLNode & node) |
---|
1509 | TRY |
---|
1510 | { |
---|
1511 | SuperClass::parse(node); |
---|
1512 | |
---|
1513 | if (node.goToChildElement()) |
---|
1514 | { |
---|
1515 | StdString nodeElementName; |
---|
1516 | do |
---|
1517 | { |
---|
1518 | StdString nodeId(""); |
---|
1519 | if (node.getAttributes().end() != node.getAttributes().find("id")) |
---|
1520 | { nodeId = node.getAttributes()["id"]; } |
---|
1521 | |
---|
1522 | nodeElementName = node.getElementName(); |
---|
1523 | std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it; |
---|
1524 | it = transformationMapList_.find(nodeElementName); |
---|
1525 | if (ite != it) |
---|
1526 | { |
---|
1527 | transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second, |
---|
1528 | nodeId, |
---|
1529 | &node))); |
---|
1530 | } |
---|
1531 | else |
---|
1532 | { |
---|
1533 | ERROR("void CAxis::parse(xml::CXMLNode & node)", |
---|
1534 | << "The transformation " << nodeElementName << " has not been supported yet."); |
---|
1535 | } |
---|
1536 | } while (node.goToNextElement()) ; |
---|
1537 | node.goToParentElement(); |
---|
1538 | } |
---|
1539 | } |
---|
1540 | CATCH_DUMP_ATTR |
---|
1541 | |
---|
1542 | |
---|
1543 | ////////////////////////////////////////////////////////////////////////////////////// |
---|
1544 | // this part is related to distribution, element definition, views and connectors // |
---|
1545 | ////////////////////////////////////////////////////////////////////////////////////// |
---|
1546 | |
---|
1547 | void CAxis::initializeLocalElement(void) |
---|
1548 | { |
---|
1549 | // after checkAttribute index of size n |
---|
1550 | int rank = CContext::getCurrent()->getIntraCommRank() ; |
---|
1551 | |
---|
1552 | CArray<size_t,1> ind(n) ; |
---|
1553 | for (int i=0;i<n;i++) ind(i)=index(i) ; |
---|
1554 | |
---|
1555 | localElement_ = new CLocalElement(rank, n_glo, ind) ; |
---|
1556 | } |
---|
1557 | |
---|
1558 | void CAxis::addFullView(void) |
---|
1559 | { |
---|
1560 | CArray<int,1> index(n) ; |
---|
1561 | for(int i=0; i<n ; i++) index(i)=i ; |
---|
1562 | localElement_ -> addView(CElementView::FULL, index) ; |
---|
1563 | } |
---|
1564 | |
---|
1565 | void CAxis::addWorkflowView(void) |
---|
1566 | { |
---|
1567 | // mask + data are included into data_index |
---|
1568 | int nk=data_index.numElements() ; |
---|
1569 | int nMask=0 ; |
---|
1570 | for(int k=0;k<nk;k++) if (data_index(k)>=0 && data_index(k)<n) nMask++ ; |
---|
1571 | |
---|
1572 | CArray<int,1> index(nMask) ; |
---|
1573 | nMask=0 ; |
---|
1574 | for(int k=0;k<nk;k++) |
---|
1575 | if (data_index(k)>=0 && data_index(k)<n) |
---|
1576 | { |
---|
1577 | index(nMask) = data_index(k) ; |
---|
1578 | nMask++ ; |
---|
1579 | } |
---|
1580 | localElement_ -> addView(CElementView::WORKFLOW, index) ; |
---|
1581 | } |
---|
1582 | |
---|
1583 | void CAxis::addModelView(void) |
---|
1584 | { |
---|
1585 | // information for model view is stored in data_index |
---|
1586 | localElement_->addView(CElementView::MODEL, data_index) ; |
---|
1587 | } |
---|
1588 | |
---|
1589 | void CAxis::computeModelToWorkflowConnector(void) |
---|
1590 | { |
---|
1591 | CLocalView* srcView=getLocalView(CElementView::MODEL) ; |
---|
1592 | CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ; |
---|
1593 | modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); |
---|
1594 | modelToWorkflowConnector_->computeConnector() ; |
---|
1595 | } |
---|
1596 | |
---|
1597 | |
---|
1598 | void CAxis::computeRemoteElement(CContextClient* client, EDistributionType type) |
---|
1599 | { |
---|
1600 | CContext* context = CContext::getCurrent(); |
---|
1601 | map<int, CArray<size_t,1>> globalIndex ; |
---|
1602 | |
---|
1603 | if (type==EDistributionType::BANDS) // Bands distribution to send to file server |
---|
1604 | { |
---|
1605 | int nbServer = client->serverSize; |
---|
1606 | int nbClient = client->clientSize ; |
---|
1607 | int rankClient = client->clientRank ; |
---|
1608 | int size = nbServer / nbClient ; |
---|
1609 | int start ; |
---|
1610 | if (nbServer%nbClient > rankClient) |
---|
1611 | { |
---|
1612 | start = (size+1) * rankClient ; |
---|
1613 | size++ ; |
---|
1614 | } |
---|
1615 | else start = size*rankClient + nbServer%nbClient ; |
---|
1616 | |
---|
1617 | for(int i=0; i<size; i++) |
---|
1618 | { |
---|
1619 | int rank=start+i ; |
---|
1620 | size_t indSize = n_glo/nbServer ; |
---|
1621 | size_t indStart ; |
---|
1622 | if (n_glo % nbServer > rank) |
---|
1623 | { |
---|
1624 | indStart = (indSize+1) * rank ; |
---|
1625 | indSize++ ; |
---|
1626 | } |
---|
1627 | else indStart = indSize*rank + n_glo%nbServer ; |
---|
1628 | |
---|
1629 | auto& globalInd = globalIndex[rank] ; |
---|
1630 | globalInd.resize(indSize) ; |
---|
1631 | for(size_t n = 0 ; n<indSize; n++) globalInd(n)=indStart+n ; |
---|
1632 | } |
---|
1633 | } |
---|
1634 | else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain |
---|
1635 | { |
---|
1636 | int nbServer = client->serverSize; |
---|
1637 | size_t nglo=n_glo ; |
---|
1638 | CArray<size_t,1> indGlo(nglo) ; |
---|
1639 | for(size_t i=0;i<nglo;i++) indGlo(i) = i ; |
---|
1640 | for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); |
---|
1641 | } |
---|
1642 | remoteElement_[client] = new CDistributedElement(n_glo, globalIndex) ; |
---|
1643 | remoteElement_[client]->addFullView() ; |
---|
1644 | } |
---|
1645 | |
---|
1646 | void CAxis::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, |
---|
1647 | CScattererConnector* &scattererConnector, const string& axisId) |
---|
1648 | { |
---|
1649 | string serverAxisId = axisId.empty() ? this->getId() : axisId ; |
---|
1650 | CContext* context = CContext::getCurrent(); |
---|
1651 | |
---|
1652 | this->sendAllAttributesToServer(client, serverAxisId) ; |
---|
1653 | |
---|
1654 | CDistributedElement scatteredElement(n_glo,globalIndex) ; |
---|
1655 | scatteredElement.addFullView() ; |
---|
1656 | scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), |
---|
1657 | context->getIntraComm(), client->getRemoteSize()) ; |
---|
1658 | scattererConnector->computeConnector() ; |
---|
1659 | |
---|
1660 | // phase 0 |
---|
1661 | // send remote element to construct the full view on server, ie without hole |
---|
1662 | CEventClient event0(getType(), EVENT_ID_AXIS_DISTRIBUTION); |
---|
1663 | CMessage message0 ; |
---|
1664 | message0<<serverAxisId<<0 ; |
---|
1665 | remoteElement_[client]->sendToServer(client,event0,message0) ; |
---|
1666 | |
---|
1667 | // phase 1 |
---|
1668 | // send the full view of element to construct the connector which connect distributed data coming from client to the full local view |
---|
1669 | CEventClient event1(getType(), EVENT_ID_AXIS_DISTRIBUTION); |
---|
1670 | CMessage message1 ; |
---|
1671 | message1<<serverAxisId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; |
---|
1672 | scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ; |
---|
1673 | |
---|
1674 | sendDistributedAttributes(client, *scattererConnector, axisId) ; |
---|
1675 | |
---|
1676 | // phase 2 send the mask : data index + mask2D |
---|
1677 | CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize()); |
---|
1678 | CArray<bool,1> maskOut ; |
---|
1679 | CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ; |
---|
1680 | workflowToFull.computeConnector() ; |
---|
1681 | maskIn=true ; |
---|
1682 | workflowToFull.transfer(maskIn,maskOut,false) ; |
---|
1683 | |
---|
1684 | // phase 3 : prepare grid scatterer connector to send data from client to server |
---|
1685 | map<int,CArray<size_t,1>> workflowGlobalIndex ; |
---|
1686 | map<int,CArray<bool,1>> maskOut2 ; |
---|
1687 | scattererConnector->transfer(maskOut, maskOut2) ; |
---|
1688 | scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ; |
---|
1689 | scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ; |
---|
1690 | // create new workflow view for scattered element |
---|
1691 | CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ; |
---|
1692 | clientToServerElement.addFullView() ; |
---|
1693 | CEventClient event2(getType(), EVENT_ID_AXIS_DISTRIBUTION); |
---|
1694 | CMessage message2 ; |
---|
1695 | message2<<serverAxisId<<2 ; |
---|
1696 | clientToServerElement.sendToServer(client, event2, message2) ; |
---|
1697 | clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), |
---|
1698 | context->getIntraComm(), client->getRemoteSize()) ; |
---|
1699 | clientToServerConnector_[client]->computeConnector() ; |
---|
1700 | |
---|
1701 | clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)); |
---|
1702 | clientFromServerConnector_[client]->computeConnector() ; |
---|
1703 | |
---|
1704 | |
---|
1705 | } |
---|
1706 | |
---|
1707 | void CAxis::recvAxisDistribution(CEventServer& event) |
---|
1708 | TRY |
---|
1709 | { |
---|
1710 | string axisId; |
---|
1711 | int phasis ; |
---|
1712 | for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> phasis ; |
---|
1713 | get(axisId)->receivedAxisDistribution(event, phasis); |
---|
1714 | } |
---|
1715 | CATCH |
---|
1716 | |
---|
1717 | |
---|
1718 | void CAxis::receivedAxisDistribution(CEventServer& event, int phasis) |
---|
1719 | TRY |
---|
1720 | { |
---|
1721 | CContext* context = CContext::getCurrent(); |
---|
1722 | if (phasis==0) // receive the remote element to construct the full view |
---|
1723 | { |
---|
1724 | localElement_ = new CLocalElement(context->getIntraCommRank(),event) ; |
---|
1725 | localElement_->addFullView() ; |
---|
1726 | // construct the local dimension and indexes |
---|
1727 | auto& globalIndex=localElement_->getGlobalIndex() ; |
---|
1728 | int nk=globalIndex.numElements() ; |
---|
1729 | int minK=n_glo,maxK=-1 ; |
---|
1730 | int nGlo=n_glo ; |
---|
1731 | int indGlo ; |
---|
1732 | for(int k=0;k<nk;k++) |
---|
1733 | { |
---|
1734 | indGlo=globalIndex(k) ; |
---|
1735 | if (indGlo<minK) minK=indGlo ; |
---|
1736 | if (indGlo>maxK) maxK=indGlo ; |
---|
1737 | } |
---|
1738 | if (maxK>=minK) { begin=minK ; n=maxK-minK+1 ; } |
---|
1739 | else {begin=0; n=0 ;} |
---|
1740 | |
---|
1741 | } |
---|
1742 | else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server |
---|
1743 | { |
---|
1744 | CContext* context = CContext::getCurrent(); |
---|
1745 | CDistributedElement* elementFrom = new CDistributedElement(event) ; |
---|
1746 | elementFrom->addFullView() ; |
---|
1747 | gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ; |
---|
1748 | gathererConnector_->computeConnector() ; |
---|
1749 | } |
---|
1750 | else if (phasis==2) |
---|
1751 | { |
---|
1752 | // delete gathererConnector_ ; |
---|
1753 | elementFrom_ = new CDistributedElement(event) ; |
---|
1754 | elementFrom_->addFullView() ; |
---|
1755 | // gathererConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ; |
---|
1756 | // gathererConnector_ -> computeConnector() ; |
---|
1757 | } |
---|
1758 | |
---|
1759 | } |
---|
1760 | CATCH |
---|
1761 | |
---|
1762 | void CAxis::setServerMask(CArray<bool,1>& serverMask, CContextClient* client) |
---|
1763 | TRY |
---|
1764 | { |
---|
1765 | CContext* context = CContext::getCurrent(); |
---|
1766 | localElement_->addView(CElementView::WORKFLOW, serverMask) ; |
---|
1767 | mask.reference(serverMask.copy()) ; |
---|
1768 | |
---|
1769 | serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ; |
---|
1770 | serverFromClientConnector_->computeConnector() ; |
---|
1771 | |
---|
1772 | serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL), |
---|
1773 | context->getIntraComm(), client->getRemoteSize()) ; |
---|
1774 | serverToClientConnector_->computeConnector() ; |
---|
1775 | } |
---|
1776 | CATCH_DUMP_ATTR |
---|
1777 | |
---|
1778 | void CAxis::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& axisId) |
---|
1779 | { |
---|
1780 | string serverAxisId = axisId.empty() ? this->getId() : axisId ; |
---|
1781 | CContext* context = CContext::getCurrent(); |
---|
1782 | |
---|
1783 | if (hasValue) |
---|
1784 | { |
---|
1785 | { // send level value |
---|
1786 | CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); |
---|
1787 | CMessage message ; |
---|
1788 | message<<serverAxisId<<string("value") ; |
---|
1789 | scattererConnector.transfer(value, client, event,message) ; |
---|
1790 | } |
---|
1791 | } |
---|
1792 | |
---|
1793 | if (hasBounds) |
---|
1794 | { |
---|
1795 | { // send bounds level value |
---|
1796 | CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); |
---|
1797 | CMessage message ; |
---|
1798 | message<<serverAxisId<<string("bounds") ; |
---|
1799 | scattererConnector.transfer(2, bounds, client, event,message) ; |
---|
1800 | } |
---|
1801 | } |
---|
1802 | |
---|
1803 | if (hasLabel) |
---|
1804 | { |
---|
1805 | { // send label |
---|
1806 | // need to transform array of string (no fixed size for string) into array of array of char |
---|
1807 | // to use connector to transfer |
---|
1808 | // the strings must have fixed size which the maximum lenght over the string label. |
---|
1809 | int maxSize=0 ; |
---|
1810 | for(int i=0; i<label.numElements();i++) |
---|
1811 | if (maxSize < label(i).size()) maxSize=label(i).size() ; |
---|
1812 | MPI_Allreduce(MPI_IN_PLACE, &maxSize,1,MPI_INT,MPI_MAX, context->getIntraComm()) ; |
---|
1813 | maxSize=maxSize+1 ; |
---|
1814 | CArray<char,2> charArray(maxSize,label.numElements()) ; |
---|
1815 | for(int j=0; j<label.numElements();j++) |
---|
1816 | { |
---|
1817 | const char* str = label(j).c_str() ; |
---|
1818 | int strSize=label(j).size()+1 ; |
---|
1819 | for(int i=0; i<strSize; i++) charArray(i,j) = str[i] ; |
---|
1820 | } |
---|
1821 | CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); |
---|
1822 | CMessage message ; |
---|
1823 | message<<serverAxisId<<string("label")<<maxSize ; |
---|
1824 | scattererConnector.transfer(maxSize, charArray, client, event,message) ; |
---|
1825 | } |
---|
1826 | } |
---|
1827 | } |
---|
1828 | |
---|
1829 | void CAxis::recvDistributedAttributes(CEventServer& event) |
---|
1830 | TRY |
---|
1831 | { |
---|
1832 | string axisId; |
---|
1833 | string type ; |
---|
1834 | for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> type ; |
---|
1835 | get(axisId)->recvDistributedAttributes(event, type); |
---|
1836 | } |
---|
1837 | CATCH |
---|
1838 | |
---|
1839 | void CAxis::recvDistributedAttributes(CEventServer& event, const string& type) |
---|
1840 | TRY |
---|
1841 | { |
---|
1842 | if (type=="value") |
---|
1843 | { |
---|
1844 | gathererConnector_->transfer(event, value, 0.); |
---|
1845 | } |
---|
1846 | else if (type=="bounds") |
---|
1847 | { |
---|
1848 | CArray<double,1> value ; |
---|
1849 | gathererConnector_->transfer(event, 2, value, 0.); |
---|
1850 | bounds.resize(2,n) ; |
---|
1851 | if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; |
---|
1852 | } |
---|
1853 | else if (type=="label") |
---|
1854 | { |
---|
1855 | int maxSize ; |
---|
1856 | for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> maxSize ; |
---|
1857 | CArray<char,1> value ; |
---|
1858 | gathererConnector_->transfer(event, maxSize, value, '\0'); |
---|
1859 | CArray<char,2> charArray(maxSize,n) ; |
---|
1860 | label.resize(n) ; |
---|
1861 | if (n>0) |
---|
1862 | { |
---|
1863 | charArray=CArray<char,2>(value.dataFirst(),shape(maxSize,n),neverDeleteData) ; |
---|
1864 | for(int j=0;j<n;j++) |
---|
1865 | { |
---|
1866 | int strSize ; |
---|
1867 | for(int i=0;i<maxSize;i++) |
---|
1868 | if (charArray(i,j)=='\0') { strSize=i ; break; } |
---|
1869 | string str(strSize,'\0') ; |
---|
1870 | for(int i=0;i<strSize;i++) str[i]=charArray(i,j) ; |
---|
1871 | label(j)=str ; |
---|
1872 | } |
---|
1873 | } |
---|
1874 | } |
---|
1875 | } |
---|
1876 | CATCH |
---|
1877 | |
---|
1878 | DEFINE_REF_FUNC(Axis,axis) |
---|
1879 | |
---|
1880 | ///--------------------------------------------------------------- |
---|
1881 | |
---|
1882 | } // namespace xios |
---|