Arcane  v3.16.2.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
TimeHistoryMngInternal.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* TimeHistoryMngInternal.cc (C) 2000-2025 */
9/* */
10/* Classe interne gérant un historique de valeurs. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/impl/internal/TimeHistoryMngInternal.h"
15
16#include "arcane/core/IMeshMng.h"
17#include "arcane/core/IPropertyMng.h"
18
19#include "arcane/utils/JSONWriter.h"
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24namespace Arcane
25{
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
32{
33 m_trace_mng->info() << "Add CurveWriter2 name=" << writer->name();
35 m_curve_writers2.insert(writer);
36}
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
42removeCurveWriter(const String& name)
43{
44 for (auto& cw : m_curve_writers2)
45 if (cw->name() == name) {
47 return;
48 }
49}
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
56{
57 OStringStream meta_data_str;
58
59 meta_data_str() << "<?xml version='1.0' ?>\n";
60 meta_data_str() << "<curves>\n";
61 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
62 TimeHistoryValue* val = i->second;
63 meta_data_str() << "<curve "
64 << " name='" << val->name() << "'"
65 << " index='" << val->index() << "'"
66 << " data-type='" << dataTypeName(val->dataType()) << "'"
67 << " sub-size='" << val->subSize() << "'";
68
69 if (!val->meshHandle().isNull()) {
70 meta_data_str() << " support='" << val->meshHandle().meshName() << "'";
71 }
72 if (val->isLocal()) {
73 meta_data_str() << " sub-domain='" << val->localSubDomainId() << "'";
74 }
75
76 meta_data_str() << "/>\n";
77 }
78 meta_data_str() << "</curves>\n";
79
80 {
81 String ss = meta_data_str.str();
82 m_th_meta_data = ss;
83 //warning() << "TimeHistoryMng MetaData: size=" << ss.len() << " v=" << ss;
84 }
85
87}
88
89/*---------------------------------------------------------------------------*/
90/*---------------------------------------------------------------------------*/
91
94{
95 m_observer_pool.addObserver(this,
97 prop_mng->writeObservable());
98
99 m_observer_pool.addObserver(this,
101 m_variable_mng->writeObservable());
102}
103
104/*---------------------------------------------------------------------------*/
105/*---------------------------------------------------------------------------*/
106
109{
110 auto p = m_properties;
111 p->setInt32("version", m_version);
112}
113
114/*---------------------------------------------------------------------------*/
115/*---------------------------------------------------------------------------*/
116
119{
120 m_global_times.add(m_common_variables.globalTime());
121 TimeHistoryAddValueArgInternal thpi(m_common_variables.m_global_time.name(), true, NULL_SUB_DOMAIN_ID);
122 addValue(thpi, m_common_variables.globalTime());
123}
124
125/*---------------------------------------------------------------------------*/
126/*---------------------------------------------------------------------------*/
127
134
135/*---------------------------------------------------------------------------*/
136/*---------------------------------------------------------------------------*/
137
140{
142 return;
143
145 TimeHistoryCurveWriterInfo infos(m_output_path, m_global_times.constView());
146 writer->beginWrite(infos);
147 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
148 const TimeHistoryValue& th = *(i->second);
149 th.dumpValues(m_trace_mng, writer, infos);
150 }
151 writer->endWrite();
152 }
153
154 else {
155
156#ifdef ARCANE_CHECK
158 bool all_need_comm = m_parallel_mng->reduce(MessagePassing::ReduceMin, m_need_comm);
159 if (all_need_comm != m_need_comm) {
160 ARCANE_FATAL("Internal error: m_need_comm not sync");
161 }
162 }
163#endif
164
165 if (m_is_master_io) {
166 TimeHistoryCurveWriterInfo infos(m_output_path, m_global_times.constView());
167 writer->beginWrite(infos);
168 // Nos courbes
169 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
170 const TimeHistoryValue& th = *(i->second);
171 th.dumpValues(m_trace_mng, writer, infos);
172 }
173
174 // Les courbes reçues.
176 Integer master_io_rank = m_parallel_mng->masterIORank();
177 UniqueArray<Int32> length(5);
178
179 for (Integer i = 0; i < m_parallel_mng->commSize(); ++i) {
180 if (i != master_io_rank) {
181 Integer nb_curve = 0;
182 m_parallel_mng->recv(ArrayView<Integer>(1, &nb_curve), i);
183 for (Integer icurve = 0; icurve < nb_curve; ++icurve) {
184 m_parallel_mng->recv(length, i);
185
186 UniqueArray<char> buf(length[0]);
187 UniqueArray<Int32> iterations_to_write(length[1]);
188 UniqueArray<Real> values_to_write(length[2]);
189
190 m_parallel_mng->recv(buf, i);
191 m_parallel_mng->recv(iterations_to_write, i);
192 m_parallel_mng->recv(values_to_write, i);
193
194 String name = String(buf.unguardedBasePointer());
195
196 if (length[4] != 0) {
197 UniqueArray<char> buf2(length[4]);
198 m_parallel_mng->recv(buf2, i);
199 String name_mesh = String(buf2.unguardedBasePointer());
200
201 TimeHistoryCurveInfo curve_info(name, name_mesh, iterations_to_write, values_to_write, length[3], i);
202 writer->writeCurve(curve_info);
203 }
204 else {
205 TimeHistoryCurveInfo curve_info(name, iterations_to_write, values_to_write, length[3], i);
206 writer->writeCurve(curve_info);
207 }
208 }
209 }
210 }
211 }
212
213 writer->endWrite();
214 }
215 else if (m_need_comm) {
216 TimeHistoryCurveWriterInfo infos(m_output_path, m_global_times.constView());
217 Integer master_io_rank = m_parallel_mng->masterIORank();
219 UniqueArray<Int32> length(5);
220 m_parallel_mng->send(ArrayView<Integer>(1, &nb_curve), master_io_rank);
221 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
222 const TimeHistoryValue& th = *(i->second);
223 String name = th.name();
224 UniqueArray<Int32> iterations_to_write;
225 UniqueArray<Real> values_to_write;
226 th.arrayToWrite(iterations_to_write, values_to_write, infos);
227
228 length[0] = arcaneCheckArraySize(name.length() + 1);
229 length[1] = iterations_to_write.size();
230 length[2] = values_to_write.size();
231 length[3] = th.subSize();
232 if (!th.meshHandle().isNull()) {
233 length[4] = arcaneCheckArraySize(th.meshHandle().meshName().length() + 1);
234 }
235 else {
236 length[4] = 0;
237 }
238
239 m_parallel_mng->send(length, master_io_rank);
240 m_parallel_mng->send(ConstArrayView<char>(length[0], static_cast<const char*>(name.localstr())), master_io_rank);
241 m_parallel_mng->send(iterations_to_write, master_io_rank);
242 m_parallel_mng->send(values_to_write, master_io_rank);
243 if (!th.meshHandle().isNull()) {
244 m_parallel_mng->send(ConstArrayView<char>(length[4], static_cast<const char*>(th.meshHandle().meshName().localstr())), master_io_rank);
245 }
246 }
247 }
248 }
249}
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253
256{
258 return;
259 if (!m_is_dump_active)
260 return;
261
265
266 m_trace_mng->info() << "Fin sortie historique: " << platform::getCurrentDateTime();
267}
268
269/*---------------------------------------------------------------------------*/
270/*---------------------------------------------------------------------------*/
271
274{
276 return;
277 for (IterT<HistoryList> i(m_history_list); i(); ++i) {
278 TimeHistoryValue& th = *(i->second);
279 th.applyTransformation(m_trace_mng, v);
280 }
281}
282
283/*---------------------------------------------------------------------------*/
284/*---------------------------------------------------------------------------*/
285
287readVariables(IMeshMng* mesh_mng, IMesh* default_mesh)
288{
289 bool need_update = false;
290
291 auto p = m_properties;
292
293 Int32 version = 0;
294 if (!p->get("version", version)) {
295 version = 1;
296 m_trace_mng->info() << "The checkpoint contains legacy format of TimeHistory variables, updating...";
297 _fromLegacyFormat(default_mesh);
298 need_update = true;
299 }
300 else if (version == 2) {
301 m_trace_mng->info() << "TimeHistory Variables version 2";
302 }
303 else {
304 ARCANE_FATAL("Unknown TimeHistory Variables format -- Found version: {0}", version);
305 }
306
307 m_trace_mng->info(4) << "readVariables resizes m_global_time to " << m_th_global_time.size();
308 m_global_times.resize(m_th_global_time.size());
310
311 m_trace_mng->info() << "Reading the values history";
312
313 IIOMng* io_mng = m_parallel_mng->ioMng();
315 if (!doc.get()) {
316 m_trace_mng->error() << " METADATA len=" << m_th_meta_data().length()
317 << " str='" << m_th_meta_data() << "'";
318 ARCANE_FATAL("The meta-data of TimeHistoryMng2 are invalid.");
319 }
320 XmlNode root_node = doc->documentNode();
321 XmlNode curves_node = root_node.child(String("curves"));
322 XmlNodeList curves = curves_node.children(String("curve"));
323
324 // v1
325 String ustr_name("name");
326 String ustr_index("index");
327 String ustr_sub_size("sub-size");
328 String ustr_data_type("data-type");
329
330 // v2
331 String ustr_support("support");
332 String ustr_sub_domain("sub-domain");
333
334 for (XmlNode curve : curves) {
335 String name = curve.attrValue(ustr_name);
336 Integer index = curve.attr(ustr_index).valueAsInteger();
337 Integer sub_size = curve.attr(ustr_sub_size).valueAsInteger();
338 String data_type_str = curve.attrValue(ustr_data_type);
339 eDataType dt = dataTypeFromName(data_type_str.localstr());
340 String support_str = curve.attrValue(ustr_support, false);
341
342 XmlNode sub_domain_node = curve.attr(ustr_sub_domain);
343 Integer sub_domain = NULL_SUB_DOMAIN_ID;
344 if (!sub_domain_node.null()) {
345 sub_domain = sub_domain_node.valueAsInteger();
346 m_need_comm = true;
347 }
348
349 if (sub_domain != NULL_SUB_DOMAIN_ID && m_parallel_mng->commRank() != sub_domain) {
350 continue;
351 }
352
353 if (name.null())
354 ARCANE_FATAL("null name for curve");
355 if (index < 0)
356 ARCANE_FATAL("Invalid index '{0}' for curve", index);
357
358 TimeHistoryValue* val = nullptr;
359 if (support_str.null()) {
360 TimeHistoryAddValueArgInternal thpi(name, true, sub_domain);
361 switch (dt) {
362 case DT_Real:
363 val = new TimeHistoryValueT<Real>(m_variable_mng, thpi, index, sub_size, isShrinkActive());
364 break;
365 case DT_Int32:
366 val = new TimeHistoryValueT<Int32>(m_variable_mng, thpi, index, sub_size, isShrinkActive());
367 break;
368 case DT_Int64:
369 val = new TimeHistoryValueT<Int64>(m_variable_mng, thpi, index, sub_size, isShrinkActive());
370 break;
371 default:
372 ARCANE_FATAL("Unsupported type");
373 }
374 if (need_update) {
375 val->fromOldToNewVariables(m_variable_mng, default_mesh);
376 }
377 }
378 else {
379 MeshHandle mh = mesh_mng->findMeshHandle(support_str);
380 TimeHistoryAddValueArgInternal thpi(TimeHistoryAddValueArg(name, true, sub_domain), mh);
381 switch (dt) {
382 case DT_Real:
383 val = new TimeHistoryValueT<Real>(thpi, index, sub_size, isShrinkActive());
384 break;
385 case DT_Int32:
386 val = new TimeHistoryValueT<Int32>(thpi, index, sub_size, isShrinkActive());
387 break;
388 case DT_Int64:
389 val = new TimeHistoryValueT<Int64>(thpi, index, sub_size, isShrinkActive());
390 break;
391 default:
392 ARCANE_FATAL("Unsupported type");
393 }
394 // Important dans le cas où on a deux historiques de même nom pour deux maillages différents,
395 // ou le même nom qu'un historique "globale".
396 name = name + "_" + mh.meshName();
397 }
398 if (sub_domain != NULL_SUB_DOMAIN_ID) {
399 name = name + "_Local";
400 }
401 m_history_list.insert(HistoryValueType(name, val));
402 }
403}
404
405/*---------------------------------------------------------------------------*/
406/*---------------------------------------------------------------------------*/
407
410{
411 Integer current_iteration = m_common_variables.globalIteration();
412 {
413 // Vérifie qu'on n'a pas plus d'éléments que d'itérations
414 // dans 'm_th_global_time'. Normalement cela ne peut arriver
415 // que lors d'un retour-arrière si les variables ont été sauvegardées
416 // au cours du pas de temps.
417 // TODO: ce test ne fonctionne pas si isShrinkActive() est vrai.
418 Integer n = m_th_global_time.size();
419 if (n > current_iteration) {
420 n = current_iteration;
421 m_th_global_time.resize(n);
422 m_trace_mng->info() << "TimeHistoryRestore: truncating TimeHistoryGlobalTime array to size n=" << n << "\n";
423 }
424 }
425 m_global_times.resize(m_th_global_time.size());
427
428 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
429 i->second->removeAfterIteration(current_iteration);
430 }
431}
432
433/*---------------------------------------------------------------------------*/
434/*---------------------------------------------------------------------------*/
435
437editOutputPath(const Directory& directory)
438{
439 m_directory = directory;
440 if (m_output_path.empty()) {
441 m_output_path = m_directory.path();
442 if (m_directory.createDirectory()) {
443 m_trace_mng->warning() << "Can't create the output directory '" << m_output_path << "'";
444 }
445 }
446}
447
448/*---------------------------------------------------------------------------*/
449/*---------------------------------------------------------------------------*/
450
453{
454 if (!m_is_master_io && (!thpi.timeHistoryAddValueArg().isLocal() || !m_enable_non_io_master_curves || !m_is_master_io_of_sd)) {
455 return;
456 }
457
458 if (thpi.timeHistoryAddValueArg().isLocal() && thpi.timeHistoryAddValueArg().localSubDomainId() != m_parallel_mng->commRank()) {
459 return;
460 }
461
462 if (!m_is_active) {
463 return;
464 }
465
466 String name_to_find = thpi.timeHistoryAddValueArg().name().clone();
467 if (!thpi.meshHandle().isNull()) {
468 // Important dans le cas où on a deux historiques de même nom pour deux maillages différents,
469 // ou le même nom qu'un historique "globale".
470 name_to_find = name_to_find + "_" + thpi.meshHandle().meshName();
471 }
472 if (thpi.timeHistoryAddValueArg().isLocal()) {
473 name_to_find = name_to_find + "_Local";
474 }
475
476 auto hl = m_history_list.find(name_to_find);
477
478 if (hl != m_history_list.end()) {
479 TimeHistoryCurveWriterInfo infos(m_output_path, m_global_times.constView());
480 hl->second->arrayToWrite(iterations, values, infos);
481 }
482 else {
483 iterations.clear();
484 values.clear();
485 }
486}
487
488/*---------------------------------------------------------------------------*/
489/*---------------------------------------------------------------------------*/
490
493{
494 m_trace_mng->debug() << "Writing of the history of values path=" << m_output_path;
495
497 m_trace_mng->info() << "Begin output history: " << platform::getCurrentDateTime();
498
499 // Ecriture via version 2 des curve writers
500 for (auto& cw_ref : m_curve_writers2) {
501 ITimeHistoryCurveWriter2* writer = cw_ref.get();
502 m_trace_mng->debug() << "Writing curves with '" << writer->name()
503 << "' date=" << platform::getCurrentDateTime();
504 dumpCurves(writer);
505 }
506 }
507}
508
509/*---------------------------------------------------------------------------*/
510/*---------------------------------------------------------------------------*/
511
514{
515 // Seul le processus master écrit.
516 Integer master_io_rank = m_parallel_mng->masterIORank();
517 if (m_is_master_io) {
518 std::ofstream ofile(m_directory.file("time_history.xml").localstr());
519 ofile << "<?xml version='1.0' ?>\n";
520 ofile << "<curves>\n";
521
522 // On écrit d'abord le nom de nos courbes.
523 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
524 const TimeHistoryValue& th = *(i->second);
525 ofile << "<curve name='";
526 if (!th.meshHandle().isNull()) {
527 ofile << th.meshHandle().meshName() << "_";
528 }
529 if (th.isLocal()) {
530 ofile << "SD" << master_io_rank << "_";
531 }
532 ofile << th.name() << "'/>\n";
533 }
534 // Puis, si les autres processus peuvent aussi avoir des courbes, on
535 // écrit aussi leurs noms.
537 for (Integer i = 0; i < m_parallel_mng->commSize(); ++i)
538 if (i != master_io_rank) {
539 Integer nb_curve = 0;
540 m_parallel_mng->recv(ArrayView<Integer>(1, &nb_curve), i);
541 for (Integer icurve = 0; icurve < nb_curve; ++icurve) {
542 UniqueArray<Int32> length(2);
543 m_parallel_mng->recv(length, i);
544
545 UniqueArray<char> buf(length[0]);
546 m_parallel_mng->recv(buf, i);
547 ofile << "<curve name='";
548
549 if (length[1] != 0) {
550 UniqueArray<char> buf2(length[1]);
551 m_parallel_mng->recv(buf2, i);
552 ofile << buf2.unguardedBasePointer() << "_";
553 }
554 ofile << "SD" << i << "_";
555 ofile << buf.unguardedBasePointer() << "'/>\n";
556 }
557 }
558 }
559 ofile << "</curves>\n";
560 }
561
562 // Si l'on n'est pas un processus écrivain mais qu'il est possible que l'on possède des courbes.
565 m_parallel_mng->send(ArrayView<Integer>(1, &nb_curve), master_io_rank);
566 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
567 const TimeHistoryValue& th = *(i->second);
568 String name = th.name();
569 UniqueArray<Int32> length(2);
570 length[0] = arcaneCheckArraySize(name.length() + 1);
571 if (th.meshHandle().isNull()) {
572 length[1] = 0;
573 m_parallel_mng->send(length, master_io_rank);
574 m_parallel_mng->send(ConstArrayView<char>(length[0], static_cast<const char*>(name.localstr())), master_io_rank);
575 }
576 else {
577 String mesh_name = th.meshHandle().meshName();
578 length[1] = arcaneCheckArraySize(mesh_name.length() + 1);
579 m_parallel_mng->send(length, master_io_rank);
580 m_parallel_mng->send(ConstArrayView<char>(length[0], static_cast<const char*>(name.localstr())), master_io_rank);
581 m_parallel_mng->send(ConstArrayView<char>(length[1], static_cast<const char*>(mesh_name.localstr())), master_io_rank);
582 }
583 }
584 }
585}
586
587/*---------------------------------------------------------------------------*/
588/*---------------------------------------------------------------------------*/
589
592{
593 // Seul le processus master écrit.
594 if (m_is_master_io) {
595
596 JSONWriter json_writer(JSONWriter::FormatFlags::None);
597 {
598 JSONWriter::Object o1(json_writer);
599 {
600 JSONWriter::Object o2(json_writer, "arcane-curves");
601 json_writer.write("version", 1);
602 {
603 Integer master_io_rank = m_parallel_mng->masterIORank();
604 json_writer.writeKey("curves");
605 json_writer.beginArray();
606
607 // On écrit d'abord le nom de nos courbes.
608 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
609 JSONWriter::Object o4(json_writer);
610 const TimeHistoryValue& th = *(i->second);
611 json_writer.write("name", th.name());
612
613 String name("");
614
615 if (!th.meshHandle().isNull()) {
616 json_writer.write("support", th.meshHandle().meshName());
617 name = name + th.meshHandle().meshName() + "_";
618 }
619
620 if (th.isLocal()) {
621 json_writer.write("sub-domain", master_io_rank);
622 name = name + "SD" + String::fromNumber(master_io_rank) + "_";
623 }
624
625 json_writer.write("unique-name", name + th.name());
626 }
627
628 // Puis, si les autres processus peuvent aussi avoir des courbes, on
629 // écrit aussi leurs noms.
631 for (Integer i = 0; i < m_parallel_mng->commSize(); ++i) {
632 if (i != master_io_rank) {
633 Integer nb_curve = 0;
634 m_parallel_mng->recv(ArrayView<Integer>(1, &nb_curve), i);
635 for (Integer icurve = 0; icurve < nb_curve; ++icurve) {
636 JSONWriter::Object o4(json_writer);
637 UniqueArray<Int32> length(2);
638 m_parallel_mng->recv(length, i);
639
640 UniqueArray<char> buf(length[0]);
641 m_parallel_mng->recv(buf, i);
642 json_writer.write("name", buf.unguardedBasePointer());
643
644 String name("");
645
646 if (length[1] != 0) {
647 UniqueArray<char> buf2(length[1]);
648 m_parallel_mng->recv(buf2, i);
649 json_writer.write("support", buf2.unguardedBasePointer());
650 name = name + buf2.unguardedBasePointer() + "_";
651 }
652
653 name = name + "SD" + String::fromNumber(i) + "_";
654
655 json_writer.write("sub-domain", i);
656 json_writer.write("unique-name", name + buf.unguardedBasePointer());
657 }
658 }
659 }
660 }
661 json_writer.endArray();
662 }
663 }
664 }
665
666 Directory out_dir(m_output_path);
667 std::ofstream ofile(out_dir.file("time_history.json").localstr());
668 ofile << json_writer.getBuffer();
669 ofile.close();
670 }
671
672 // Si l'on n'est pas un processus écrivain mais qu'il est possible que l'on possède des courbes.
674
675 Integer master_io_rank = m_parallel_mng->masterIORank();
676
678 m_parallel_mng->send(ArrayView<Integer>(1, &nb_curve), master_io_rank);
679 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
680 const TimeHistoryValue& th = *(i->second);
681 String name = th.name();
682 UniqueArray<Int32> length(2);
683 length[0] = arcaneCheckArraySize(name.length() + 1);
684 if (th.meshHandle().isNull()) {
685 length[1] = 0;
686 m_parallel_mng->send(length, master_io_rank);
687 m_parallel_mng->send(ConstArrayView<char>(length[0], static_cast<const char*>(name.localstr())), master_io_rank);
688 }
689 else {
690 String mesh_name = th.meshHandle().meshName();
691 length[1] = arcaneCheckArraySize(mesh_name.length() + 1);
692 m_parallel_mng->send(length, master_io_rank);
693 m_parallel_mng->send(ConstArrayView<char>(length[0], static_cast<const char*>(name.localstr())), master_io_rank);
694 m_parallel_mng->send(ConstArrayView<char>(length[1], static_cast<const char*>(mesh_name.localstr())), master_io_rank);
695 }
696 }
697 }
698}
699
700/*---------------------------------------------------------------------------*/
701/*---------------------------------------------------------------------------*/
702
703template <class DataType>
706{
707 if (!m_is_active) {
708 return;
709 }
710
711 if (thpi.timeHistoryAddValueArg().isLocal()) {
712 m_need_comm = true;
713 }
714
715 if (!m_is_master_io && (!thpi.timeHistoryAddValueArg().isLocal() || !m_enable_non_io_master_curves || !m_is_master_io_of_sd)) {
716 return;
717 }
718
719 if (thpi.timeHistoryAddValueArg().isLocal() && thpi.timeHistoryAddValueArg().localSubDomainId() != m_parallel_mng->commRank()) {
720 return;
721 }
722
723 String name_to_find = thpi.timeHistoryAddValueArg().name().clone();
724 if (!thpi.meshHandle().isNull()) {
725 // Important dans le cas où on a deux historiques de même nom pour deux maillages différents,
726 // ou le même nom qu'un historique "globale".
727 name_to_find = name_to_find + "_" + thpi.meshHandle().meshName();
728 }
729 if (thpi.timeHistoryAddValueArg().isLocal()) {
730 name_to_find = name_to_find + "_Local";
731 }
732
733 Integer iteration = m_common_variables.globalIteration();
734
735 if (!thpi.timeHistoryAddValueArg().endTime() && iteration != 0)
736 --iteration;
737
738 auto hl = m_history_list.find(name_to_find);
739 TimeHistoryValueT<DataType>* th = nullptr;
740 // Trouvé, on le retourne.
741 if (hl != m_history_list.end())
742 th = dynamic_cast<TimeHistoryValueT<DataType>*>(hl->second);
743 else {
744 if (!thpi.meshHandle().isNull()) {
745 th = new TimeHistoryValueT<DataType>(thpi, (Integer)m_history_list.size(), values.size(), isShrinkActive());
746 }
747 else {
748 th = new TimeHistoryValueT<DataType>(m_variable_mng, thpi, (Integer)m_history_list.size(), values.size(), isShrinkActive());
749 }
750 m_history_list.insert(HistoryValueType(name_to_find, th));
751 }
752 if (!th)
753 return;
754 if (values.size() != th->subSize()) {
755 ARCANE_FATAL("Bad subsize for curve '{0}' current={1} old={2}",
756 name_to_find, values.size(), th->subSize());
757 }
758 th->addValue(values, iteration);
759}
760
761/*---------------------------------------------------------------------------*/
762/*---------------------------------------------------------------------------*/
763
766{
767 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
768 TimeHistoryValue* v = i->second;
769 delete v;
770 }
771}
772
773/*---------------------------------------------------------------------------*/
774/*---------------------------------------------------------------------------*/
775
777_fromLegacyFormat(IMesh* default_mesh)
778{
779 IVariable* ptr_old_global_time = m_variable_mng->findMeshVariable(default_mesh, "TimeHistoryGlobalTime");
780 IVariable* ptr_old_meta_data = m_variable_mng->findMeshVariable(default_mesh, "TimeHistoryMetaData");
781 if (ptr_old_global_time == nullptr || ptr_old_meta_data == nullptr)
782 ARCANE_FATAL("TimeHistoryGlobalTime or TimeHistoryMetaData is not found.");
783
784 VariableArrayReal old_global_time(ptr_old_global_time);
785 VariableScalarString old_meta_data(ptr_old_meta_data);
786
787 m_th_global_time.resize(old_global_time.size());
788 m_th_global_time.copy(old_global_time);
789 m_th_meta_data.swapValues(old_meta_data);
790
791 old_global_time.resize(0);
792 old_meta_data.reset();
793}
794
795/*---------------------------------------------------------------------------*/
796/*---------------------------------------------------------------------------*/
797
800{
801 m_curve_writers2.erase(writer);
802}
803
804/*---------------------------------------------------------------------------*/
805/*---------------------------------------------------------------------------*/
806
807template void TimeHistoryMngInternal::
809
810template void TimeHistoryMngInternal::
812
813template void TimeHistoryMngInternal::
815
816/*---------------------------------------------------------------------------*/
817/*---------------------------------------------------------------------------*/
818
819} // End namespace Arcane
820
821/*---------------------------------------------------------------------------*/
822/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable d'un tableau d'un type T.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
void clear()
Supprime les éléments du tableau.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
interval d'itérateurs constant
Classe gérant un répertoire.
Definition Directory.h:33
virtual String file(const String &file_name) const
Retourne le chemin complet du fichier file_name dans le répertoire.
Definition Directory.cc:138
Interface du gestionnaire des entrées sorties.
Definition IIOMng.h:42
virtual IXmlDocumentHolder * parseXmlString(const String &str, const String &name)=0
Lit et analyse le fichier XML contenu dans la chaîne str.
Interface du gestionnaire des maillages.
Definition IMeshMng.h:40
virtual MeshHandle * findMeshHandle(const String &name, bool throw_exception)=0
Recherche le maillage de nom name.
Interface du gestionnaire des propriétés.
virtual IObservable * writeObservable()=0
Observable pour l'écriture.
Interface d'un écrivain d'une courbe.
virtual String name() const =0
Nom de l'écrivain.
virtual void endWrite()=0
Notifie la fin de l'écriture.
virtual void beginWrite(const TimeHistoryCurveWriterInfo &infos)=0
Notifie un début d'écriture.
virtual void writeCurve(const TimeHistoryCurveInfo &infos)=0
Ecrit une courbe.
Interface d'un objet transformant les courbes d'historiques.
Interface d'une variable.
Definition IVariable.h:56
interval d'itérateursCette classe gère un couple d'itérateurs autorisant la modification des éléments...
Ecrivain au format JSON.
Definition JSONWriter.h:33
Handle sur un maillage.
Definition MeshHandle.h:47
bool isNull() const
Indique si le handle est nul (il ne référence aucun maillage existant ou non)
Definition MeshHandle.h:162
Flot de sortie lié à une String.
T * get() const
Retourne l'objet référé par l'instance.
Definition Ptr.h:121
Référence à une instance.
Encapsulation d'un pointeur qui se détruit automatiquement.
Definition ScopedPtr.h:44
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:304
Int64 length() const
Retourne la longueur de la chaîne.
Definition String.cc:338
String clone() const
Clone cette chaîne.
Definition String.cc:412
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
Classe étendant les arguments lors d'un ajout de valeur dans un historique de valeur.
Informations pour l'écriture d'une courbe.
Informations sur l'écriture des courbes.
bool isShrinkActive() const override
Retourne un booléen indiquant si l'historique est compressé
void updateMetaData() override
Méthode permettant de mettre à jour les méta-données des courbes.
bool m_is_master_io
True si je suis le gestionnaire des IO.
void addNowInGlobalTime() override
Méthode permettant d'ajouter le GlobalTime actuel au tableau des GlobalTimes.
void addValue(const TimeHistoryAddValueArgInternal &thpi, Real value) override
Méthode permettant d'ajouter une valeur à un historique.
void _dumpSummaryOfCurves()
Méthode permettant de sortir un fichier JSON avec le nom de chaque courbe sortie en format GNUPLOT ai...
bool m_is_master_io_of_sd
True si je suis le gestionnaire des IO pour mon sous-domaine.
void _removeCurveWriter(const Ref< ITimeHistoryCurveWriter2 > &writer)
Méthode permettant de retirer un écrivain.
void updateGlobalTimeCurve() override
Méthode permettant de copier le tableau de GlobalTime dans la variable globale GlobalTime.
void resizeArrayAfterRestore() override
Méthode permettant de redimensionner les tableaux de valeurs après une reprise.
void addObservers(IPropertyMng *prop_mng) override
Méthode permettant de rajouter les observers sauvegardant l'historique avant une protection.
bool m_is_dump_active
Indique si les dump sont actifs.
void removeCurveWriter(const String &name) override
Méthode permettant de retirer un écrivain.
void readVariables(IMeshMng *mesh_mng, IMesh *default_mesh) override
Méthode permettant de récupérer les courbes précédemment écrites lors d'une reprise.
void dumpHistory() override
Méthode permettant d'écrire toutes les courbes à l'aide de tous les writers enregistrés.
void _dumpSummaryOfCurvesLegacy()
Méthode permettant de sortir un fichier XML avec le nom de chaque courbe sortie en format GNUPLOT.
HistoryList m_history_list
Liste des historiques.
void _addHistoryValue(const TimeHistoryAddValueArgInternal &thpi, ConstArrayView< DataType > values)
Méthode permettant d'ajouter des valeurs à un historique de valeurs.
VariableArrayReal m_th_global_time
Tableau des instants de temps.
bool m_enable_non_io_master_curves
Indique si l'ecriture de courbes par des procs non io_master est possible.
void _dumpCurvesAllWriters()
Méthode permettant de sortir toutes les courbes avec tous les writers.
void applyTransformation(ITimeHistoryTransformer *v) override
Applique la transformation v à l'ensemble des courbes.
void iterationsAndValues(const TimeHistoryAddValueArgInternal &thpi, UniqueArray< Int32 > &iterations, UniqueArray< Real > &values) override
Méthode permettant de sortir les itérations et les valeurs d'un historique.
void dumpCurves(ITimeHistoryCurveWriter2 *writer) override
Méthode permettant d"écrire les courbes à l'aide du writer fourni.
bool m_io_master_write_only
Indique si les writers doivent être appelé par tous les processus.
void _saveProperties()
Méthode permettant de sauver les propriétés des metadatas.
VariableScalarString m_th_meta_data
Infos des historiques.
void _fromLegacyFormat(IMesh *default_mesh)
Méthode permettant de convertir l'ancien format vers le nouveau.
void editOutputPath(const Directory &directory) override
Méthode permettant de changer le répertoire de sortie des courbes.
RealUniqueArray m_global_times
Liste des temps globaux.
bool m_need_comm
Indique si au moins une courbe est non local (donc nécessite des communications).
bool m_is_active
Indique si le service est actif.
void addCurveWriter(Ref< ITimeHistoryCurveWriter2 > writer) override
Méthode permettant d'ajouter un écrivain pour la sortie des courbes.
Historique de valeurs du type T.
void addValue(ConstArrayView< DataType > values, Integer iteration)
Méthode permettant d'ajouter des valeurs à une itération.
Classe de base d'un historique de valeurs.
Integer index() const
Index de l'historique dans la liste.
const MeshHandle & meshHandle() const
Méthode permettant de récupérer le MeshHandle enregistré.
const String & name() const
Nom de l'historique.
eDataType dataType() const
Type de données de l'historique.
virtual void applyTransformation(ITraceMng *msg, ITimeHistoryTransformer *v)=0
Méthode permettant d'appliquer une transformation sur les valeurs de l'historique de valeur.
virtual void fromOldToNewVariables(IVariableMng *vm, IMesh *default_mesh)=0
Méthode permettant de convertir les variables d'anciennes sauvegardes vers le nouveau format.
Integer localSubDomainId() const
Méthode permettant de récupérer l'id du sous-domaine à qui appartient cet historique.
virtual void arrayToWrite(UniqueArray< Int32 > &iterations, UniqueArray< Real > &values, const TimeHistoryCurveWriterInfo &infos) const =0
Méthode permettant de récupérer les itérations et les valeurs d'un historique de valeur.
bool isLocal() const
Méthode permettant de savoir si c'est un historique global ou local à un sous-domaine.
virtual void dumpValues(ITraceMng *msg, ITimeHistoryCurveWriter2 *writer, const TimeHistoryCurveWriterInfo &infos) const =0
Imprime les valeurs de l'historique avec l'écrivain writer.
Vecteur 1D de données avec sémantique par valeur (style STL).
virtual void resize(Integer new_size)
Redimensionne le tableau pour contenir new_size éléments.
void reset()
Réinitialise la variable avec sa valeur par défaut.
Liste de noeuds d'un arbre DOM.
Definition XmlNodeList.h:33
Noeud d'un arbre DOM.
Definition XmlNode.h:51
XmlNode attr(const String &name, bool throw_exception=false) const
Retourne l'attribut de nom name.
Definition XmlNode.cc:248
XmlNode child(const String &name) const
Noeud fils de celui-ci de nom name.
Definition XmlNode.cc:64
XmlNodeList children(const String &name) const
Ensemble des noeuds fils de ce noeud ayant pour nom name.
Definition XmlNode.cc:93
bool null() const
Vrai si le noeud est nul.
Definition XmlNode.h:294
Integer valueAsInteger(bool throw_exception=false) const
Valeur du noeud convertie en entier.
Definition XmlNode.cc:432
VariableRefArrayT< Real > VariableArrayReal
Variable tableau de type réels.
VariableRefScalarT< String > VariableScalarString
Variable scalaire de type chaine de caractère.
@ ReduceMin
Minimum des valeurs.
ARCCORE_BASE_EXPORT String getCurrentDateTime()
Date et l'heure courante sous la forme ISO 8601.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
Int32 Integer
Type représentant un entier.
eDataType
Type d'une donnée.
Definition DataTypes.h:39
@ DT_Int32
Donnée de type entier 32 bits.
Definition DataTypes.h:43
@ DT_Int64
Donnée de type entier 64 bits.
Definition DataTypes.h:44
@ DT_Real
Donnée de type réel.
Definition DataTypes.h:41
ARCANE_DATATYPE_EXPORT eDataType dataTypeFromName(const char *name, bool &has_error)
Trouve le type associé à name.
Definition DataTypes.cc:92
const char * dataTypeName(eDataType type)
Nom du type de donnée.
Definition DataTypes.cc:70
std::int32_t Int32
Type entier signé sur 32 bits.