Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
VariableMng.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* VariableMng.cc (C) 2000-2026 */
9/* */
10/* Class managing all variables. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/impl/internal/VariableMng.h"
15
16#include "arcane/utils/Deleter.h"
17#include "arcane/utils/StringBuilder.h"
18#include "arcane/utils/FatalErrorException.h"
19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/JSONWriter.h"
21#include "arcane/utils/OStringStream.h"
22#include "arcane/utils/Math.h"
23
24#include "arcane/core/ArcaneException.h"
25#include "arcane/core/VarRefEnumerator.h"
26#include "arcane/core/IModule.h"
27#include "arcane/core/ISubDomain.h"
28#include "arcane/core/IObservable.h"
29#include "arcane/core/VariableInfo.h"
30#include "arcane/core/VariableBuildInfo.h"
31#include "arcane/core/VariableFactoryRegisterer.h"
32#include "arcane/core/IVariableFactory.h"
33#include "arcane/core/ItemGroup.h"
34#include "arcane/core/IMesh.h"
35#include "arcane/core/MeshHandle.h"
36#include "arcane/core/IParallelMng.h"
37#include "arcane/core/ITimeLoopMng.h"
38#include "arcane/core/IEntryPoint.h"
39#include "arcane/core/Properties.h"
40#include "arcane/core/VariableStatusChangedEventArgs.h"
41
42#include "arcane/impl/VariableUtilities.h"
43#include "arcane/impl/internal/VariableSynchronizerMng.h"
44
45#include <exception>
46#include <set>
47#include <vector>
48
49// TODO: handle the hash in 64-bit version.
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
54namespace Arcane
55{
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
60extern "C++" IVariableMng*
61arcaneCreateVariableMng(ISubDomain* sd)
62{
63 auto vm = new VariableMng(sd);
64 vm->build();
65 vm->initialize();
66 return vm;
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
79, m_sub_domain(sd)
80, m_parallel_mng(sd->parallelMng())
81, m_vni_map(2000, true)
82, m_write_observable(IObservable::createDefault())
83, m_read_observable(IObservable::createDefault())
84, m_utilities(new VariableUtilities(this))
85, m_variable_io_writer_mng(new VariableIOWriterMng(this))
86, m_variable_io_reader_mng(new VariableIOReaderMng(this))
87, m_variable_synchronizer_mng(new VariableSynchronizerMng(this))
88{
89}
90
91/*---------------------------------------------------------------------------*/
92/*---------------------------------------------------------------------------*/
93
101{
102 delete m_variable_synchronizer_mng;
103
104 delete m_variable_io_reader_mng;
105 delete m_variable_io_writer_mng;
106 delete m_utilities;
107
108 m_write_observable->detachAllObservers();
109 m_read_observable->detachAllObservers();
110
111 delete m_write_observable;
112 delete m_read_observable;
113
114 m_variable_factories.each(Deleter());
115}
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
121build()
122{
123 String s = platform::getEnvironmentVariable("ARCANE_TRACE_VARIABLE_CREATION");
124 if (!s.null())
125 VariableRef::setTraceCreation(true);
126}
127
128/*---------------------------------------------------------------------------*/
129/*---------------------------------------------------------------------------*/
130
133{
134 m_time_stats = m_parallel_mng->timeStats();
135
136 VariableFactoryRegisterer* vff = VariableFactoryRegisterer::firstVariableFactory();
137 while (vff) {
138 IVariableFactory* vf = vff->createFactory();
139 String full_name = vf->fullTypeName();
140 // Checks that no factory with the same name exists.
141 if (m_variable_factory_map.find(full_name) != m_variable_factory_map.end()) {
142 ARCANE_FATAL("VariableFactoryMap already contains a factory for the same type '{0}'",
143 full_name);
144 }
145 m_variable_factory_map.insert(VariableFactoryPair(full_name, vf));
146 m_variable_factories.add(vf);
147 info(5) << "Add variable factory kind=" << vff->itemKind()
148 << " data_type=" << vff->dataType()
149 << " dim=" << vff->dimension()
150 << " multi_tag=" << vff->multiTag()
151 << " full_name=" << full_name
152 << " addr=" << vf;
153 vff = vff->nextVariableFactory();
154 }
155
156 m_variable_synchronizer_mng->initialize();
157}
158
159/*---------------------------------------------------------------------------*/
160/*---------------------------------------------------------------------------*/
161
164{
165 //WARNING: this leads to calls to removeVariable()
167
168 OStringStream var_str;
169 UniqueArray<IVariable*> remaining_vars;
170 for (const auto& i : m_full_name_variable_map) {
171 IVariable* v = i.second;
172 if (v->nbReference() == 0)
173 delete v;
174 else {
175 remaining_vars.add(v);
176 var_str() << " " << v->fullName() << " (" << v->nbReference() << ")";
177 }
178 }
179 bool is_check = arcaneIsCheck();
180 const bool has_remaining_vars = !remaining_vars.empty();
181 if (has_remaining_vars && is_check)
182 pwarning() << "The following variables are still referenced: "
183 << var_str.str()
184 << " (set the environment variable ARCANE_TRACE_VARIABLE_CREATION"
185 << " to get the stack trace)";
186 bool has_trace = VariableRef::hasTraceCreation();
187 if (has_trace) {
188 for (const auto& i : remaining_vars) {
189 for (VarRefEnumerator ivar(i); ivar.hasNext(); ++ivar) {
190 VariableRef* var = *ivar;
191 info() << " variable name=" << var->name()
192 << " stack=" << var->assignmentStackTrace();
193 }
194 }
195 }
196
197 // Explicitly calls 'unregisterVariable()' on the remaining variables.
198 // Without this, if the instance 'this' is destroyed before the variables
199 // remain are, it will cause a crash (Read after free). This
200 // does not normally happen for C++ but can happen for wrapping.
201 if (has_remaining_vars) {
202 // Copies the references into a temporary array
203 // because calls to unregisterVariable() modify the ivar iterator
204 // and also m_full_name_variable_map.
205 UniqueArray<VariableRef*> remaining_refs;
206 for (const auto& i : remaining_vars)
207 for (VarRefEnumerator ivar(i); ivar.hasNext(); ++ivar)
208 remaining_refs.add(*ivar);
209 for (VariableRef* r : remaining_refs)
210 r->unregisterVariable();
211 if (is_check)
212 info() << "Remaining variables after cleanup n=" << m_full_name_variable_map.size();
213 }
214
216}
217
218/*---------------------------------------------------------------------------*/
219/*---------------------------------------------------------------------------*/
220
223{
224 for (const auto& i : m_full_name_variable_map) {
225 IVariable* v = i.second;
226 ItemGroup group = v->itemGroup();
227 if (group.null())
228 continue;
229 if (group.mesh() == mesh) {
230 v->setUsed(false);
231 }
232 }
233}
234
235/*---------------------------------------------------------------------------*/
236/*---------------------------------------------------------------------------*/
237
240{
241 ARCANE_UNUSED(ref);
242 ++m_nb_created_variable_reference;
243}
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
250{
251 ARCANE_UNUSED(ref);
252}
253
254/*---------------------------------------------------------------------------*/
255/*---------------------------------------------------------------------------*/
256
259{
260 const String& full_name = var->fullName();
261 subDomain()->checkId("VariableMng::checkVariable()", full_name);
262 if (var->itemKind() != IK_Unknown && var->itemFamilyName().null())
263 ARCANE_FATAL("Bad Variable full-name={0} name={1}", var->fullName(), var->name());
264
265 info(5) << "Add variable"
266 << " name=" << var->name()
267 << " full_name=" << full_name
268 << " datatype=" << var->dataType()
269 << " kind=" << var->itemKind();
270
272 vni.m_local_name = var->name();
273 vni.m_family_name = var->itemFamilyName();
274 vni.m_mesh_name = var->meshName();
275 m_vni_map.add(vni, var);
276
277 m_full_name_variable_map.insert(FullNameVariablePair(full_name, var));
278 m_variables_changed = true;
279 m_used_variables_changed = true;
280 ++m_nb_created_variable;
282 IModule* module = nullptr;
283 if (ep)
284 module = ep->module();
285 m_variable_creation_modules.insert(std::make_pair(var, module));
287 m_on_variable_added.notify(eargs);
288}
289
290/*---------------------------------------------------------------------------*/
291/*---------------------------------------------------------------------------*/
292
295{
296 int p = var->property();
297 if (p & IVariable::PTemporary) {
298 debug() << "** ** REMOVE " << var->name() << " " << var->nbReference()
299 << " property=" << p
300 << " nodump=" << (p & IVariable::PNoDump)
301 << " tmp=" << (p & IVariable::PTemporary)
302 << " norestore=" << (p & IVariable::PNoRestore);
303 }
305 m_on_variable_removed.notify(eargs);
306 {
307 ItemGroup var_group = var->itemGroup();
308 // Retire this variable from all groups [well defined but on ItemGroupImplNull]
309 if (!var_group.null())
310 var_group.internal()->detachObserver(var);
311 // Remove this variable from existing variables, then destroy it
313 {
315 vni.m_local_name = var->name();
316 vni.m_family_name = var->itemFamilyName();
317 vni.m_mesh_name = var->meshName();
318 m_vni_map.remove(vni);
319 }
320 m_variables_changed = true;
321 m_used_variables_changed = true;
322 m_variable_creation_modules.erase(var);
323 delete var;
324 }
325}
326
327/*---------------------------------------------------------------------------*/
328/*---------------------------------------------------------------------------*/
329
331checkVariable(const VariableInfo& infos)
332{
334 vni.m_local_name = infos.localName();
335 vni.m_family_name = infos.itemFamilyName();
336 vni.m_mesh_name = infos.meshName();
337
338 if (infos.itemKind() != IK_Unknown && infos.meshName().null())
339 ARCANE_FATAL("Mesh variable without a mesh full-name={0} name={1}", infos.fullName(), infos.localName());
340
341 // If it is a mesh variable, check that no global variable not linked to a mesh
342 // has the same name.
343 if (arcaneIsCheck()) {
344 if (!infos.meshName().null()) {
345 String check_name = infos.localName();
346 if (findVariableFullyQualified(check_name)) {
347 ARCANE_FATAL("Mesh variable has the same name that a global variable (name={0})", check_name);
348 }
349 }
350 else {
351 // If it is a global variable, check that no mesh variable has the same name.
352 String check_name = String("Mesh0_") + infos.localName();
353 if (findVariableFullyQualified(check_name)) {
354 ARCANE_FATAL("Global variable has the same name that a mesh variable (name={0})", check_name);
355 }
356 }
357 }
358
359 IVariable* var = nullptr;
360 //VNIMap::Data* var_data = m_vni_map.lookup(vni);
361
362 //cerr << "** CHECK " << name << ' ' << infos.dataType() << ' ' << infos.kind() << '\n';
363 VNIMap::Data* var_data = m_vni_map.lookup(vni);
364 if (var_data) {
365 // A variable with the same name as \a var already exists.
366 // In this case, it is necessary to check that its kind and type are the same.
367 // it has the same kind and the same type.
368 var = var_data->value();
369 //cerr << "** FIND " << prv->name() << ' ' << prv->dataType() << ' ' << prv->kind() << '\n';
370 if (infos.dataType() != var->dataType() ||
371 infos.itemKind() != var->itemKind() ||
372 infos.dimension() != var->dimension()) {
373 throw BadVariableKindTypeException(A_FUNCINFO, var, infos.itemKind(),
374 infos.dataType(), infos.dimension());
375 }
376 // For partial variable: if exists already must be defined on the same group, otherwise fatal
377 if (infos.isPartial()) {
378 if (infos.itemGroupName() != var->itemGroupName())
379 throw BadPartialVariableItemGroupNameException(A_FUNCINFO, var, infos.itemGroupName());
380 }
381 }
382 return var;
383}
384
385/*---------------------------------------------------------------------------*/
386/*---------------------------------------------------------------------------*/
387
389findVariable(const String& name)
390{
392 if (v)
393 return v;
394 v = findVariableFullyQualified(String("Node_") + name);
395 if (v)
396 return v;
397 v = findVariableFullyQualified(String("Edge_") + name);
398 if (v)
399 return v;
400 v = findVariableFullyQualified(String("Face_") + name);
401 if (v)
402 return v;
403 v = findVariableFullyQualified(String("Cell_") + name);
404 if (v)
405 return v;
406 return nullptr;
407}
408
409/*---------------------------------------------------------------------------*/
410/*---------------------------------------------------------------------------*/
411
413findMeshVariable(IMesh* mesh, const String& name)
414{
415 String mesh_name = mesh->name();
416 mesh_name = mesh_name + "_";
417 IVariable* v = findVariableFullyQualified(mesh_name + name);
418 if (v)
419 return v;
420 v = findVariableFullyQualified(mesh_name + "Node_" + name);
421 if (v)
422 return v;
423 v = findVariableFullyQualified(mesh_name + "Edge_" + name);
424 if (v)
425 return v;
426 v = findVariableFullyQualified(mesh_name + "Face_" + name);
427 if (v)
428 return v;
429 v = findVariableFullyQualified(mesh_name + "Cell_" + name);
430 if (v)
431 return v;
432 return nullptr;
433}
434
435/*---------------------------------------------------------------------------*/
436/*---------------------------------------------------------------------------*/
437
440{
441 auto i = m_full_name_variable_map.find(name);
442 if (i != m_full_name_variable_map.end())
443 return i->second;
444 return nullptr;
445}
446
447/*---------------------------------------------------------------------------*/
448/*---------------------------------------------------------------------------*/
449
452{
453 bool is_bad = true;
454 String name;
455 while (is_bad) {
456 name = String("ArcaneTemporary") + m_generate_name_id;
457 // Check that the generated name does not correspond to an existing variable
458 if (findVariable(name))
460 else
461 is_bad = false;
462 }
463 info() << "** GENERATED NAME =" << name;
464 return name;
465}
466
467/*---------------------------------------------------------------------------*/
468/*---------------------------------------------------------------------------*/
469
471dumpList(std::ostream& o, IModule* c)
472{
473 o << " ** VariableMng::Variable list\n";
474 for (const auto& i : m_full_name_variable_map) {
475 for (VarRefEnumerator ivar(i.second); ivar.hasNext(); ++ivar) {
476 if ((*ivar)->module() != c)
477 continue;
478 _dumpVariable(*(*ivar), o);
479 }
480 }
481}
482
483/*---------------------------------------------------------------------------*/
484/*---------------------------------------------------------------------------*/
485
487dumpList(std::ostream& o)
488{
489 o << " ** VariableMng::Variable list\n";
490 for (const auto& i : m_full_name_variable_map) {
491 for (VarRefEnumerator ivar(i.second); ivar.hasNext(); ++ivar) {
492 _dumpVariable(*(*ivar), o);
493 }
494 }
495 {
496 Real mem_used = 0;
497 for (const auto& i : m_full_name_variable_map)
498 mem_used += i.second->allocatedMemory();
499 o << " ** VariableMng::Allocated memory : " << mem_used;
500 o << '\n';
501 }
502}
503
504/*---------------------------------------------------------------------------*/
505/*---------------------------------------------------------------------------*/
506
508_dumpVariable(const VariableRef& var, std::ostream& o)
509{
510 o << " ** Variable: " << &var << " : ";
511 o.width(15);
512 o << var.name() << " = ";
513 var.print(o);
514 o << " (Type " << var.dataType() << ")\n";
515}
516
517/*---------------------------------------------------------------------------*/
518/*---------------------------------------------------------------------------*/
519
521initializeVariables(bool is_continue)
522{
523 ARCANE_UNUSED(is_continue);
524
525 info() << "Initialisation des variables";
526 for (const auto& i : m_full_name_variable_map) {
527 for (VarRefEnumerator ivar(i.second); ivar.hasNext(); ++ivar) {
528 VariableRef* var_ref = *ivar;
529 IModule* module = var_ref->module();
530 if (module && !module->used())
531 continue;
532 IVariable* var = var_ref->variable();
533 if (var->isUsed())
534 continue;
535 var_ref->setUsed(true);
536 }
537 }
538}
539
540/*---------------------------------------------------------------------------*/
541/*---------------------------------------------------------------------------*/
542
545{
546 for (const auto& i : m_full_name_variable_map) {
547 for (VarRefEnumerator ivar(i.second); ivar.hasNext(); ++ivar) {
548 if ((*ivar)->module() == c)
549 v.add(*ivar);
550 }
551 }
552}
553
554/*---------------------------------------------------------------------------*/
555/*---------------------------------------------------------------------------*/
556
558variables()
559{
560 if (m_variables_changed) {
561 m_variables_changed = false;
562 m_variables.clear();
563 for (const auto& i : m_full_name_variable_map) {
564 m_variables.add(i.second);
565 }
566 }
567 return m_variables;
568}
569
570/*---------------------------------------------------------------------------*/
571/*---------------------------------------------------------------------------*/
572
575{
576 if (m_used_variables_changed) {
577 m_used_variables_changed = false;
578 m_used_variables.clear();
579 for (const auto& i : m_full_name_variable_map) {
580 IVariable* var = i.second;
581 if (var->isUsed())
582 m_used_variables.add(var);
583 }
584 }
585 return m_used_variables;
586}
587
588/*---------------------------------------------------------------------------*/
589/*---------------------------------------------------------------------------*/
590
591bool VariableMng::
592isVariableToSave(IVariable& var)
593{
594 if (!var.isUsed())
595 return false;
596 bool no_dump = var.property() & (IVariable::PNoDump | IVariable::PTemporary);
597 if (no_dump)
598 return false;
600 if (mesh && !mesh->properties()->getBool("dump"))
601 return false;
602 return true;
603}
604
605/*---------------------------------------------------------------------------*/
606/*---------------------------------------------------------------------------*/
607
610{
611 m_variable_io_writer_mng->writeCheckpoint(service);
612}
613
614/*---------------------------------------------------------------------------*/
615/*---------------------------------------------------------------------------*/
616
619{
620 m_variable_io_writer_mng->writePostProcessing(post_processor);
621}
622
623/*---------------------------------------------------------------------------*/
624/*---------------------------------------------------------------------------*/
625
628{
629 m_variable_io_writer_mng->writeVariables(writer, vars, false);
630}
631
632/*---------------------------------------------------------------------------*/
633/*---------------------------------------------------------------------------*/
634
637{
638 m_variable_io_writer_mng->writeVariables(writer, filter, false);
639}
640
641/*---------------------------------------------------------------------------*/
642/*---------------------------------------------------------------------------*/
643
644VariableRef* VariableMng::
645_createVariableFromType(const String& full_type, const VariableBuildInfo& vbi)
646{
647 auto i = m_variable_factory_map.find(full_type);
648 if (i == m_variable_factory_map.end())
649 ARCANE_FATAL("No factory to create variable name={0} type={1}", vbi.name(), full_type);
650
651 IVariableFactory* vf = i->second;
652 info(5) << "Automatic creation of the variable"
653 << " name=" << vbi.name()
654 << " family=" << vbi.itemFamilyName()
655 << " type=" << full_type
656 << " vf=" << vf;
657 VariableRef* var_ref = vf->createVariable(vbi);
658 // Add the variable to a list to ensure it will be properly
659 // destroyed.
660 m_auto_create_variables.add(var_ref);
661 return var_ref;
662}
663
664/*---------------------------------------------------------------------------*/
665/*---------------------------------------------------------------------------*/
666
667/*---------------------------------------------------------------------------*/
668/*---------------------------------------------------------------------------*/
669
672{
673 m_variable_io_reader_mng->readCheckpoint(service);
674}
675
676/*---------------------------------------------------------------------------*/
677/*---------------------------------------------------------------------------*/
678
681{
682 m_variable_io_reader_mng->readCheckpoint(infos);
683}
684
685/*---------------------------------------------------------------------------*/
686/*---------------------------------------------------------------------------*/
687
690{
691 m_variable_io_reader_mng->readVariables(reader, filter);
692}
693
694/*---------------------------------------------------------------------------*/
695/*---------------------------------------------------------------------------*/
696
702{
703 Real total_size = 0;
704 if (vars.empty()) {
705 for (const auto& i : m_full_name_variable_map) {
706 IVariable* var = i.second;
707 if (var->isUsed()) {
708 Real n = (Real)(var->allocatedMemory());
709 total_size += n;
710 }
711 }
712 }
713 else {
714 for (VariableCollection::Enumerator i(vars); ++i;) {
715 IVariable* var = *i;
716 if (var->isUsed())
717 total_size += (Real)(var->allocatedMemory());
718 }
719 }
720 total_size /= 1.0e6;
721
722 return total_size;
723}
724
725/*---------------------------------------------------------------------------*/
726/*---------------------------------------------------------------------------*/
727
729synchronizerMng() const
730{
731 return m_variable_synchronizer_mng;
732}
733
734/*---------------------------------------------------------------------------*/
735/*---------------------------------------------------------------------------*/
736
739{
740 public:
741
742 bool operator()(IVariable* v1, IVariable* v2)
743 {
744 return v1->allocatedMemory() > v2->allocatedMemory();
745 }
746};
747
749dumpStats(std::ostream& ostr, bool is_verbose)
750{
751 ostr.precision(20);
752 ostr << "\nMemory statistics for variables:\n";
753 ostr << " Number of created variables: " << m_nb_created_variable << '\n';
754 ostr << " Number of created variables reference: " << m_nb_created_variable_reference << '\n';
755 ostr << " Number of currently allocated variables: " << m_full_name_variable_map.size() << '\n';
756 ostr << " Number of currently reference: " << m_variables_ref.count() << '\n';
757
758 // Statistics on used memory
759 Integer total_nb_var = 0;
760 Integer nb_var[NB_ITEM_KIND];
761 Real mem_used[NB_ITEM_KIND];
762 Real mem_used_array = 0.;
763 Real mem_used_particle = 0.;
764 Real mem_used_link = 0.;
765 Real total_mem_used = 0.;
766 Integer nb_var_array = 0;
767 Integer nb_var_particle = 0;
768 Integer nb_var_link = 0;
769 for (Integer i = 0; i < NB_ITEM_KIND; ++i) {
770 mem_used[i] = 0;
771 nb_var[i] = 0;
772 }
773
774 // Get the number of cells to calculate statistics on average memory per cell.
775 Integer nb_cell = 1;
776 if (subDomain()->defaultMesh())
777 nb_cell = subDomain()->defaultMesh()->allCells().size();
778 if (nb_cell == 0)
779 nb_cell = 1;
780
781 typedef std::map<IModule*, std::set<IVariable*>> ModuleVariableMap;
782 std::set<IVariable*> variables_with_module;
783 UniqueArray<IVariable*> memory_sorted_variables;
784
785 ModuleVariableMap modules_variables;
786 for (const auto& i : m_full_name_variable_map) {
787 //for( VariableRefList::Enumerator ivar(m_variables_ref); ++ivar; ){
788 IVariable* var = i.second;
789 if (!var->isUsed())
790 continue;
791 // No statistics on scalar variables
792 if (var->dimension() == 0)
793 continue;
794 for (VarRefEnumerator ivar(var); ivar.hasNext(); ++ivar) {
795 VariableRef* vref = *ivar;
796 IModule* var_module = vref->module();
797 // If the variable does not have a module, search for the possible module
798 // that created it
799 if (!var_module)
800 var_module = m_variable_creation_modules[var];
801 if (var_module) {
802 variables_with_module.insert(var);
803 modules_variables[var_module].insert(var);
804 }
805 }
806 }
807
808 for (const auto& i : m_full_name_variable_map) {
809 IVariable* var = i.second;
810 // No statistics on unused variables
811 if (!var->isUsed())
812 continue;
813 // No statistics on scalar variables
814 if (var->dimension() == 0)
815 continue;
816 memory_sorted_variables.add(var);
817 // If the variable does not have an associated module, it is placed in
818 // the list of variables without a module
819 if (variables_with_module.find(var) == variables_with_module.end())
820 modules_variables[0].insert(var);
821 ++total_nb_var;
822 eItemKind ik = var->itemKind();
823 Real mem = var->allocatedMemory();
824 total_mem_used += mem;
825 if (is_verbose)
826 ostr << "Var: <" << var->name() << "> Kind=" << itemKindName(ik) << " Mem=" << mem << '\n';
827 switch (ik) {
828 case IK_Node:
829 case IK_Edge:
830 case IK_Face:
831 case IK_Cell:
832 case IK_DoF:
833 mem_used[ik] += mem;
834 ++nb_var[ik];
835 break;
836 case IK_Particle:
837 mem_used_particle += mem;
838 ++nb_var_particle;
839 break;
840 case IK_Unknown:
841 mem_used_array += mem;
842 ++nb_var_array;
843 break;
844 }
845 }
846
847 ostr << "Memory repartition by module:\n";
848 ostr << Trace::Width(30) << ""
849 << Trace::Width(7) << ""
850 << Trace::Width(12) << ""
851 << Trace::Width(14) << "Memory (Mo)"
852 << Trace::Width(10) << ""
853 << Trace::Width(7) << " "
854 << Trace::Width(13) << "Memory (Ko)"
855 << '\n';
856 ostr << Trace::Width(30) << "Module"
857 << Trace::Width(7) << "Nvar"
858 << Trace::Width(12) << "Private"
859 << Trace::Width(12) << "Shared"
860 << Trace::Width(12) << "Total"
861 << Trace::Width(7) << "%"
862 << Trace::Width(13) << "per cell"
863 << "\n\n";
864 String pr_true("X ");
865 String pr_false(" ");
866 for (ModuleVariableMap::const_iterator imodvar = modules_variables.begin();
867 imodvar != modules_variables.end(); ++imodvar) {
868 IModule* module = imodvar->first;
869 Real private_mem_used = 0.0;
870 Real shared_mem_used = 0.0;
871 for (std::set<IVariable*>::const_iterator i = imodvar->second.begin();
872 i != imodvar->second.end(); ++i) {
873 IVariable* var = *i;
874 Real mem_used2 = var->allocatedMemory();
875 bool is_private = var->nbReference() == 1;
876 if (is_private)
877 private_mem_used += mem_used2;
878 else
879 shared_mem_used += mem_used2;
880 if (is_verbose)
881 ostr << "Var: <" << var->name() << "> Kind=" << itemKindName(var->itemKind())
882 << " Mem=" << mem_used << " private?=" << is_private << '\n';
883 }
884 String module_name = "None";
885 if (module)
886 module_name = module->name();
887 Real module_mem_used = private_mem_used + shared_mem_used;
888 ostr << Trace::Width(30) << module_name
889 << Trace::Width(7) << imodvar->second.size()
890 << Trace::Width(12) << String::fromNumber(private_mem_used / 1e6, 3)
891 << Trace::Width(12) << String::fromNumber(shared_mem_used / 1e6, 3)
892 << Trace::Width(12) << String::fromNumber(module_mem_used / 1e6, 3)
893 << Trace::Width(7) << String::fromNumber(100.0 * module_mem_used / total_mem_used, 1) << "%"
894 << Trace::Width(12) << String::fromNumber(module_mem_used / ((Real)nb_cell * 1000.0), 2)
895 << '\n';
896 }
897 ostr << '\n';
898 ostr << Trace::Width(30) << "TOTAL"
899 << Trace::Width(7) << total_nb_var
900 << Trace::Width(12) << ""
901 << Trace::Width(12) << ""
902 << Trace::Width(12) << String::fromNumber(total_mem_used / 1e6, 3)
903 << Trace::Width(7) << " "
904 << Trace::Width(13) << String::fromNumber(total_mem_used / ((Real)nb_cell * 1000.0), 2)
905 << '\n';
906
907 if (is_verbose) {
908 for (Integer i = 0; i < NB_ITEM_KIND; ++i) {
909 ostr << "Variable " << itemKindName((eItemKind)i) << " N=" << nb_var[i]
910 << " Memory=" << mem_used[i] << '\n';
911 }
912 ostr << "Variable Particle N=" << nb_var_particle
913 << " Memory=" << mem_used_particle << '\n';
914 ostr << "Variable Link N=" << nb_var_link
915 << " Memory=" << mem_used_link << '\n';
916 ostr << "Variable Array N=" << nb_var_array
917 << " Memory=" << mem_used_array << '\n';
918 ostr << "Variable Total N=" << total_nb_var
919 << " Memory=" << total_mem_used << '\n';
920 }
921
922 std::sort(std::begin(memory_sorted_variables), std::end(memory_sorted_variables),
924
925 Integer nb_var_to_display = memory_sorted_variables.size();
926 if (!is_verbose)
927 nb_var_to_display = math::min(nb_var_to_display, 15);
928 ostr << "\nBiggest variables (D=Dump, E=Exchange R=Restore):\n";
929 ostr << Trace::Width(45) << "Variable"
930 << Trace::Width(10) << "Kind"
931 << Trace::Width(16) << "Memory (Ko)"
932 << Trace::Width(14) << "per cell (o)"
933 << Trace::Width(7) << "D E R"
934 << "\n\n";
935 for (Integer i = 0; i < nb_var_to_display; ++i) {
936 IVariable* var = memory_sorted_variables[i];
937 Real mem_used2 = var->allocatedMemory();
938 //ostr << "Var: <" << var->name() << "> Kind=" << itemKindName(var->itemKind())
939 //<< " Mem=" <<var->allocatedMemory() << '\n';
940
941 StringBuilder properties;
942 int var_property = var->property();
943 bool is_no_exchange = (var_property & IVariable::PNoExchange);
944 if (var->itemKind() == IK_Unknown)
945 // Only mesh variables can be exchanged
946 is_no_exchange = true;
947 properties += (var_property & IVariable::PNoDump) ? pr_false : pr_true;
948 properties += (is_no_exchange) ? pr_false : pr_true;
949 properties += (var_property & IVariable::PNoRestore) ? pr_false : pr_true;
950 ostr << Trace::Width(45) << var->name()
951 << Trace::Width(10) << itemKindName(var->itemKind())
952 << Trace::Width(14) << String::fromNumber(mem_used2 / 1e3, 3)
953 << Trace::Width(12) << String::fromNumber(mem_used2 / ((Real)nb_cell), 1)
954 << Trace::Width(12) << properties.toString()
955 << '\n';
956 }
957}
958
959/*---------------------------------------------------------------------------*/
960/*---------------------------------------------------------------------------*/
961
964{
965 writer.writeKey("Variables");
966 writer.beginArray();
967 for (const auto& i : m_full_name_variable_map) {
968 IVariable* var = i.second;
969 if (var->dimension() == 0)
970 continue;
971 {
972 JSONWriter::Object o(writer);
973 writer.write("Used", var->isUsed());
974 Real mem = var->allocatedMemory();
975 writer.write("Name", var->name());
976 writer.write("DataType", dataTypeName(var->dataType()));
977 writer.write("Dimension", (Int64)var->dimension());
978 writer.write("NbElement", (Int64)var->nbElement());
979 writer.write("ItemFamily", var->itemFamilyName());
980 writer.write("Mesh", var->meshName());
981 writer.write("Group", var->itemGroupName());
982 writer.write("Property", (Int64)var->property());
983 writer.write("AllocatedMemory", mem);
984 }
985 }
986 writer.endArray();
987}
988
989/*---------------------------------------------------------------------------*/
990/*---------------------------------------------------------------------------*/
991
992void VariableMng::
993_removeAllShMemVariables()
994{
995 UniqueArray<IVariable*> shmem_vars;
996 for (const auto& [fst, var] : m_full_name_variable_map) {
997 if (var->property() & IVariable::PInShMem)
998 shmem_vars.add(var);
999 }
1000 for (Integer i = 0; i < m_auto_create_variables.count(); ++i) {
1001 VariableRef* var = m_auto_create_variables[i];
1002 if (var->property() & IVariable::PInShMem) {
1003 //The variable will be destroyed right after with removeVariable(var).
1004 m_auto_create_variables.removeAt(i--);
1005 }
1006 }
1007 for (IVariable* var : shmem_vars) {
1008 removeVariable(var);
1009 }
1010}
1011
1012/*---------------------------------------------------------------------------*/
1013/*---------------------------------------------------------------------------*/
1014
1015} // End namespace Arcane
1016
1017/*---------------------------------------------------------------------------*/
1018/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Integer size() const
Number of elements in the vector.
bool empty() const
Capacity (number of allocated elements) of the vector.
void add(ConstReferenceType val)
Adds element val to the end of the array.
Exception for an invalid partial variable item group name.
Exception for an invalid variable kind/type.
Checkpoint reading information.
Integer count() const
Number of elements in the collection.
Utility class for destroying objects allocated by new.
Definition Deleter.h:33
Interface for the protection/recovery reading service.
Interface of the checkpoint/recovery write service.
Interface for reading variable data.
Definition IDataReader.h:35
Interface for writing variable data.
Definition IDataWriter.h:45
Interface of a module entry point.
Definition IEntryPoint.h:35
virtual CellGroup allCells()=0
Group of all cells.
Interface of a module.
Definition IModule.h:40
virtual bool used() const =0
true if the module is used.
Interface for a writer for post-processing information.
Interface of the subdomain manager.
Definition ISubDomain.h:75
virtual void checkId(const String &where, const String &id)=0
Checks if an identifier is valid.
virtual IMesh * defaultMesh()=0
Default mesh.
virtual ITimeLoopMng * timeLoopMng()=0
Returns the time loop manager.
virtual IEntryPoint * currentEntryPoint()=0
Returns the entry point currently being executed or 0 if there is none.
Interface for a variable factory.
virtual const String & fullTypeName() const =0
Full name of the variable type.
Functor of a filter applicable to variables.
Variable manager interface.
Interface of the variable synchronization manager.
Interface of a variable.
Definition IVariable.h:40
virtual Real allocatedMemory() const =0
Memory size (in Bytes) used by the variable.
virtual eDataType dataType() const =0
Data type managed by the variable (Real, Integer, ...).
virtual String meshName() const =0
Name of the associated mesh (null if none).
virtual void setUsed(bool v)=0
Sets the usage state of the variable.
virtual String itemFamilyName() const =0
Name of the associated family (null if none).
virtual String fullName() const =0
Full variable name (with family prefix).
@ PNoExchange
Indicates that the variable should not be exchanged.
Definition IVariable.h:130
@ PTemporary
Indicates that the variable is temporary.
Definition IVariable.h:114
@ PInShMem
Indicates that the variable must be allocated in shared memory.
Definition IVariable.h:156
@ PNoRestore
Indicates that the variable should not be restored.
Definition IVariable.h:120
@ PNoDump
Indicates that the variable should not be saved.
Definition IVariable.h:62
virtual int property() const =0
Returns the properties of the variable.
virtual eItemKind itemKind() const =0
Kind of mesh entities on which the variable is based.
virtual Integer nbReference() const =0
Number of references on this variable.
virtual Integer dimension() const =0
Dimension of the variable.
virtual bool isUsed() const =0
Usage state of the variable.
virtual ItemGroup itemGroup() const =0
Associated mesh group.
virtual Integer nbElement() const =0
Number of elements of the variable.
virtual String itemGroupName() const =0
Name of the associated entity group.
virtual MeshHandle meshHandle() const =0
Mesh associated with the variable.
virtual String name() const =0
Variable name.
void detachObserver(const void *ref)
Detaches an observer.
Mesh entity group.
Definition ItemGroup.h:51
ItemGroupImpl * internal() const
Returns the group implementation.
Definition ItemGroup.h:125
Integer size() const
Number of elements in the group.
Definition ItemGroup.h:93
bool null() const
true means the group is the null group
Definition ItemGroup.h:75
IMesh * mesh() const
Mesh to which this group belongs (0 for the null group).
Definition ItemGroup.h:131
IMesh * _internalMeshOrNull() const
Definition MeshHandle.h:180
Output stream linked to a String.
Unicode character string constructor.
bool null() const
Returns true if the string is null.
Definition String.cc:306
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
TraceMessage pwarning() const
Formatting the stream by length.
1D data vector with value semantics (STL style).
Parameters necessary for building a variable.
Integer dimension() const
Dimension of the variable created by this factory.
IVariableFactory * createFactory()
Creates a factory for this variable type.
Integer multiTag() const
Tag indicating the multiple type (0 if not multiple, 1 if multiple, 2 if multiple deprecated).
eDataType dataType() const
Data type of the variable created by this factory.
eItemKind itemKind() const
Kind of data variables of the variable created by this factory.
VariableFactoryRegisterer * nextVariableFactory() const
Next VariableFactory (0 if the last).
Information characterizing a variable.
bool isPartial() const
Indicates if the variable is partial.
const String & itemFamilyName() const
Name of the entity family to which the variable is associated.
const String & localName() const
Name of the variable.
eItemKind itemKind() const
Mesh entity type.
const String & itemGroupName() const
Name of the entity group to which the variable is associated.
Integer dimension() const
Dimension.
eDataType dataType() const
Element type.
const String & meshName() const
Name of the mesh to which the variable is associated.
const String & fullName() const
Full name of the variable (associated with the family).
Variable manager.
Definition VariableMng.h:57
IVariable * checkVariable(const VariableInfo &infos) override
Checks a variable.
Real exportSize(const VariableCollection &vars) override
IVariable * findVariableFullyQualified(const String &name) override
Returns the fully qualified variable named name or 0 if no such name exists.
void dumpList(std::ostream &, IModule *) override
Displays the list of variables managed by a module.
void _dumpVariable(const VariableRef &v, std::ostream &o)
Writes the value of variable v to the stream o.
void addVariable(IVariable *var) override
Adds a variable.
ISubDomain * m_sub_domain
Subdomain manager.
void dumpStatsJSON(JSONWriter &writer) override
Writes statistics with the writer writer.
Integer m_generate_name_id
Number used to generate a variable name.
List< VariableRef * > m_auto_create_variables
List of variables created automatically during a restart.
FullNameVariableMap m_full_name_variable_map
List of variables by full name.
void readVariables(IDataReader *, IVariableFilter *) override
Reads all variables.
void writeVariables(IDataWriter *, const VariableCollection &vars) override
Exports the variables.
void detachMeshVariables(IMesh *mesh) override
Detaches variables associated with the mesh mesh.
ITraceMng * traceMng() override
Message manager.
String generateTemporaryVariableName() override
Generates a name for a temporary variable.
void removeVariableRef(VariableRef *) override
Removes a reference to a variable.
ISubDomain * subDomain() override
Sub-domain manager.
IVariable * findVariable(const String &name) override
Returns the variable named name or 0 if no such name exists.
VariableFactoryMap::value_type VariableFactoryPair
Pair of the list of variables by full name.
VariableCollection usedVariables() override
List of used variables.
void removeVariable(IVariable *var) override
Removes a variable.
void build() override
Constructs the instance members.
void addVariableRef(VariableRef *ref) override
Adds a reference to a variable.
IVariable * findMeshVariable(IMesh *mesh, const String &name) override
Returns the mesh variable named name or 0 if no such name exists.
void initialize() override
Initializes the instance. The instance is not usable until this method has been called.
void removeAllVariables() override
Removes and destroys the variables managed by this manager.
VariableRefList m_variables_ref
List of variables.
FullNameVariableMap::value_type FullNameVariablePair
Pair of the list of variables by full name.
void writeCheckpoint(ICheckpointWriter *) override
Writes variables for a checkpoint.
IParallelMng * parallelMng() const override
Associated parallelism manager.
void writePostProcessing(IPostProcessorWriter *writer) override
Writes variables for post-processing.
IVariableSynchronizerMng * synchronizerMng() const override
Interface of the variable synchronization manager.
~VariableMng() override
Destroys the manager.
VariableCollection variables() override
List of variables.
void initializeVariables(bool) override
Initializes the variables.
void dumpStats(std::ostream &ostr, bool is_verbose) override
Writes statistics about variables to the stream ostr.
VariableMng(ISubDomain *sd)
Constructs a variable manager for the case pn.
void readCheckpoint(ICheckpointReader *) override
Reads all variables from a checkpoint.
Reference to a variable.
Definition VariableRef.h:56
virtual eDataType dataType() const
Variable type (Real, Integer, ...).
virtual void print(std::ostream &o) const
Prints the variable value.
virtual IModule * module() const
Module associated with the variable (or nullptr, if none).
IVariable * variable() const
Associated variable.
String name() const
Variable name.
const String & assignmentStackTrace() const
Call stack at the time of assigning this instance.
Variable sorter based on used memory size.
Arguments of the event notifying a change in the state of a variable.
Variable synchronizer manager.
Utility functions for variables.
__host__ __device__ Real2 min(Real2 a, Real2 b)
Returns the minimum of two Real2.
Definition MathUtils.h:346
String getEnvironmentVariable(const String &name)
Environment variable named name.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
Collection< VariableRef * > VariableRefCollection
Collection of variables.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
eItemKind
Mesh entity type.
@ IK_Particle
Particle mesh entity.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Unknown
Unknown or uninitialized mesh entity.
@ IK_Face
Face mesh entity.
@ IK_DoF
Degree of Freedom mesh entity.
@ IK_Edge
Edge mesh entity.
const char * itemKindName(eItemKind kind)
Entity kind name.
double Real
Type representing a real number.
const char * dataTypeName(eDataType type)
Data type name.
Definition DataTypes.cc:72