Arcane  v3.16.4.0
Documentation développeur
Tout Classes Espaces de nommage Fichiers Fonctions Variables Définitions de type Énumérations Valeurs énumérées Amis Macros Groupes Pages Concepts
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.
536 // Même si "m_io_master_write_only" est égal à false, ce fichier est
537 // forcement écrit par un seul processus.
539 for (Integer i = 0; i < m_parallel_mng->commSize(); ++i)
540 if (i != master_io_rank) {
541 Integer nb_curve = 0;
542 m_parallel_mng->recv(ArrayView<Integer>(1, &nb_curve), i);
543 for (Integer icurve = 0; icurve < nb_curve; ++icurve) {
544 UniqueArray<Int32> length(2);
545 m_parallel_mng->recv(length, i);
546
547 UniqueArray<char> buf(length[0]);
548 m_parallel_mng->recv(buf, i);
549 ofile << "<curve name='";
550
551 if (length[1] != 0) {
552 UniqueArray<char> buf2(length[1]);
553 m_parallel_mng->recv(buf2, i);
554 ofile << buf2.unguardedBasePointer() << "_";
555 }
556 ofile << "SD" << i << "_";
557 ofile << buf.unguardedBasePointer() << "'/>\n";
558 }
559 }
560 }
561 ofile << "</curves>\n";
562 }
563
564 // Si l'on n'est pas un processus écrivain mais qu'il est possible que l'on possède des courbes.
567 m_parallel_mng->send(ArrayView<Integer>(1, &nb_curve), master_io_rank);
568 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
569 const TimeHistoryValue& th = *(i->second);
570 String name = th.name();
571 UniqueArray<Int32> length(2);
572 length[0] = arcaneCheckArraySize(name.length() + 1);
573 if (th.meshHandle().isNull()) {
574 length[1] = 0;
575 m_parallel_mng->send(length, master_io_rank);
576 m_parallel_mng->send(ConstArrayView<char>(length[0], static_cast<const char*>(name.localstr())), master_io_rank);
577 }
578 else {
579 String mesh_name = th.meshHandle().meshName();
580 length[1] = arcaneCheckArraySize(mesh_name.length() + 1);
581 m_parallel_mng->send(length, master_io_rank);
582 m_parallel_mng->send(ConstArrayView<char>(length[0], static_cast<const char*>(name.localstr())), master_io_rank);
583 m_parallel_mng->send(ConstArrayView<char>(length[1], static_cast<const char*>(mesh_name.localstr())), master_io_rank);
584 }
585 }
586 }
587}
588
589/*---------------------------------------------------------------------------*/
590/*---------------------------------------------------------------------------*/
591
594{
595 // Seul le processus master écrit.
596 if (m_is_master_io) {
597
598 JSONWriter json_writer(JSONWriter::FormatFlags::None);
599 {
600 JSONWriter::Object o1(json_writer);
601 {
602 JSONWriter::Object o2(json_writer, "arcane-curves");
603 json_writer.write("version", 1);
604 {
605 Integer master_io_rank = m_parallel_mng->masterIORank();
606 json_writer.writeKey("curves");
607 json_writer.beginArray();
608
609 // On écrit d'abord le nom de nos courbes.
610 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
611 JSONWriter::Object o4(json_writer);
612 const TimeHistoryValue& th = *(i->second);
613 json_writer.write("name", th.name());
614
615 String name("");
616
617 if (!th.meshHandle().isNull()) {
618 json_writer.write("support", th.meshHandle().meshName());
619 name = name + th.meshHandle().meshName() + "_";
620 }
621
622 if (th.isLocal()) {
623 json_writer.write("sub-domain", master_io_rank);
624 name = name + "SD" + String::fromNumber(master_io_rank) + "_";
625 }
626
627 json_writer.write("unique-name", name + th.name());
628 }
629
630 // Puis, si les autres processus peuvent aussi avoir des courbes, on
631 // écrit aussi leurs noms.
632 // Même si "m_io_master_write_only" est égal à false, ce fichier est
633 // forcement écrit par un seul processus.
635 for (Integer i = 0; i < m_parallel_mng->commSize(); ++i) {
636 if (i != master_io_rank) {
637 Integer nb_curve = 0;
638 m_parallel_mng->recv(ArrayView<Integer>(1, &nb_curve), i);
639 for (Integer icurve = 0; icurve < nb_curve; ++icurve) {
640 JSONWriter::Object o4(json_writer);
641 UniqueArray<Int32> length(2);
642 m_parallel_mng->recv(length, i);
643
644 UniqueArray<char> buf(length[0]);
645 m_parallel_mng->recv(buf, i);
646 json_writer.write("name", buf.unguardedBasePointer());
647
648 String name("");
649
650 if (length[1] != 0) {
651 UniqueArray<char> buf2(length[1]);
652 m_parallel_mng->recv(buf2, i);
653 json_writer.write("support", buf2.unguardedBasePointer());
654 name = name + buf2.unguardedBasePointer() + "_";
655 }
656
657 name = name + "SD" + String::fromNumber(i) + "_";
658
659 json_writer.write("sub-domain", i);
660 json_writer.write("unique-name", name + buf.unguardedBasePointer());
661 }
662 }
663 }
664 }
665 json_writer.endArray();
666 }
667 }
668 }
669
670 Directory out_dir(m_output_path);
671 std::ofstream ofile(out_dir.file("time_history.json").localstr());
672 ofile << json_writer.getBuffer();
673 ofile.close();
674 }
675
676 // Si l'on n'est pas un processus écrivain mais qu'il est possible que l'on possède des courbes.
678
679 Integer master_io_rank = m_parallel_mng->masterIORank();
680
682 m_parallel_mng->send(ArrayView<Integer>(1, &nb_curve), master_io_rank);
683 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
684 const TimeHistoryValue& th = *(i->second);
685 String name = th.name();
686 UniqueArray<Int32> length(2);
687 length[0] = arcaneCheckArraySize(name.length() + 1);
688 if (th.meshHandle().isNull()) {
689 length[1] = 0;
690 m_parallel_mng->send(length, master_io_rank);
691 m_parallel_mng->send(ConstArrayView<char>(length[0], static_cast<const char*>(name.localstr())), master_io_rank);
692 }
693 else {
694 String mesh_name = th.meshHandle().meshName();
695 length[1] = arcaneCheckArraySize(mesh_name.length() + 1);
696 m_parallel_mng->send(length, master_io_rank);
697 m_parallel_mng->send(ConstArrayView<char>(length[0], static_cast<const char*>(name.localstr())), master_io_rank);
698 m_parallel_mng->send(ConstArrayView<char>(length[1], static_cast<const char*>(mesh_name.localstr())), master_io_rank);
699 }
700 }
701 }
702}
703
704/*---------------------------------------------------------------------------*/
705/*---------------------------------------------------------------------------*/
706
707template <class DataType>
710{
711 if (!m_is_active) {
712 return;
713 }
714
715 if (thpi.timeHistoryAddValueArg().isLocal()) {
716 m_need_comm = true;
717 }
718
719 if (!m_is_master_io && (!thpi.timeHistoryAddValueArg().isLocal() || !m_enable_non_io_master_curves || !m_is_master_io_of_sd)) {
720 return;
721 }
722
723 if (thpi.timeHistoryAddValueArg().isLocal() && thpi.timeHistoryAddValueArg().localSubDomainId() != m_parallel_mng->commRank()) {
724 return;
725 }
726
727 String name_to_find = thpi.timeHistoryAddValueArg().name().clone();
728 if (!thpi.meshHandle().isNull()) {
729 // Important dans le cas où on a deux historiques de même nom pour deux maillages différents,
730 // ou le même nom qu'un historique "globale".
731 name_to_find = name_to_find + "_" + thpi.meshHandle().meshName();
732 }
733 if (thpi.timeHistoryAddValueArg().isLocal()) {
734 name_to_find = name_to_find + "_Local";
735 }
736
737 Integer iteration = m_common_variables.globalIteration();
738
739 if (!thpi.timeHistoryAddValueArg().endTime() && iteration != 0)
740 --iteration;
741
742 auto hl = m_history_list.find(name_to_find);
743 TimeHistoryValueT<DataType>* th = nullptr;
744 // Trouvé, on le retourne.
745 if (hl != m_history_list.end())
746 th = dynamic_cast<TimeHistoryValueT<DataType>*>(hl->second);
747 else {
748 if (!thpi.meshHandle().isNull()) {
749 th = new TimeHistoryValueT<DataType>(thpi, (Integer)m_history_list.size(), values.size(), isShrinkActive());
750 }
751 else {
752 th = new TimeHistoryValueT<DataType>(m_variable_mng, thpi, (Integer)m_history_list.size(), values.size(), isShrinkActive());
753 }
754 m_history_list.insert(HistoryValueType(name_to_find, th));
755 }
756 if (!th)
757 return;
758 if (values.size() != th->subSize()) {
759 ARCANE_FATAL("Bad subsize for curve '{0}' current={1} old={2}",
760 name_to_find, values.size(), th->subSize());
761 }
762 th->addValue(values, iteration);
763}
764
765/*---------------------------------------------------------------------------*/
766/*---------------------------------------------------------------------------*/
767
770{
771 for (ConstIterT<HistoryList> i(m_history_list); i(); ++i) {
772 TimeHistoryValue* v = i->second;
773 delete v;
774 }
775}
776
777/*---------------------------------------------------------------------------*/
778/*---------------------------------------------------------------------------*/
779
781_fromLegacyFormat(IMesh* default_mesh)
782{
783 IVariable* ptr_old_global_time = m_variable_mng->findMeshVariable(default_mesh, "TimeHistoryGlobalTime");
784 IVariable* ptr_old_meta_data = m_variable_mng->findMeshVariable(default_mesh, "TimeHistoryMetaData");
785 if (ptr_old_global_time == nullptr || ptr_old_meta_data == nullptr)
786 ARCANE_FATAL("TimeHistoryGlobalTime or TimeHistoryMetaData is not found.");
787
788 VariableArrayReal old_global_time(ptr_old_global_time);
789 VariableScalarString old_meta_data(ptr_old_meta_data);
790
791 m_th_global_time.resize(old_global_time.size());
792 m_th_global_time.copy(old_global_time);
793 m_th_meta_data.swapValues(old_meta_data);
794
795 old_global_time.resize(0);
796 old_meta_data.reset();
797}
798
799/*---------------------------------------------------------------------------*/
800/*---------------------------------------------------------------------------*/
801
804{
805 m_curve_writers2.erase(writer);
806}
807
808/*---------------------------------------------------------------------------*/
809/*---------------------------------------------------------------------------*/
810
811template void TimeHistoryMngInternal::
813
814template void TimeHistoryMngInternal::
816
817template void TimeHistoryMngInternal::
819
820/*---------------------------------------------------------------------------*/
821/*---------------------------------------------------------------------------*/
822
823} // End namespace Arcane
824
825/*---------------------------------------------------------------------------*/
826/*---------------------------------------------------------------------------*/
#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:35
String file(const String &file_name) const override
Retourne le chemin complet du fichier file_name dans le répertoire.
Definition Directory.cc:120
Interface du gestionnaire des entrées sorties.
Definition IIOMng.h:36
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:35
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.