Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ModuleMaster.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/* ModuleMaster.cc (C) 2000-2025 */
9/* */
10/* Master module. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/Iterator.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/Array.h"
19#include "arcane/utils/Enumerator.h"
20#include "arcane/utils/Collection.h"
21#include "arcane/utils/IOnlineDebuggerService.h"
22
23#include "arcane/core/ModuleMaster.h"
24#include "arcane/core/EntryPoint.h"
25#include "arcane/core/CaseOptionsMain.h"
26#include "arcane/core/ITimeHistoryMng.h"
27#include "arcane/core/IVariableMng.h"
28#include "arcane/core/ISubDomain.h"
29#include "arcane/core/IApplication.h"
30#include "arcane/core/IModuleMng.h"
31#include "arcane/core/ITimeLoopMng.h"
32#include "arcane/core/IParallelMng.h"
33#include "arcane/core/ICaseMng.h"
34#include "arcane/core/IModuleMng.h"
35#include "arcane/core/ModuleBuildInfo.h"
36#include "arcane/core/ITimeLoopService.h"
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41namespace Arcane
42{
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
47extern "C++" ARCANE_CORE_EXPORT IModuleMaster*
48arcaneCreateModuleMaster(ISubDomain* sd)
49{
50 ModuleBuildInfo mbi(sd, sd->defaultMeshHandle(), "ArcaneMasterInternal");
51 ModuleMaster* m = new ModuleMaster(mbi);
52 return m;
53}
54
55/*---------------------------------------------------------------------------*/
56/*---------------------------------------------------------------------------*/
57
61, CommonVariables(this)
62{
64
65 addEntryPoint(this, "ArcaneTimeLoopBegin",
68 addEntryPoint(this, "ArcaneTimeLoopEnd",
71 addEntryPoint(this, "ArcaneMasterStartInit",
74 addEntryPoint(this, "ArcaneMasterInit",
77 addEntryPoint(this, "ArcaneMasterContinueInit",
81 addEntryPoint(this, "ArcaneMasterLoopExit",
82 &ModuleMaster::_masterLoopExit,
83 IEntryPoint::WExit,
85 addEntryPoint(this, "ArcaneMasterLoopMeshChanged",
86 &ModuleMaster::_masterMeshChanged,
89 addEntryPoint(this, "ArcaneMasterLoopRestore",
90 &ModuleMaster::_masterRestore,
93}
94
95/*---------------------------------------------------------------------------*/
96/*---------------------------------------------------------------------------*/
97
103
104/*---------------------------------------------------------------------------*/
105/*---------------------------------------------------------------------------*/
106
109{
111 m_global_time = 0.0;
114 m_global_cpu_time = 0.0;
118
119 // Updates the dataset options that depend on a marching table.
120 ICaseMng* com = subDomain()->caseMng();
121 com->updateOptions(0.0, 0.0, 0);
122
123 _masterStartInit();
124}
125
126/*---------------------------------------------------------------------------*/
127/*---------------------------------------------------------------------------*/
128
131{
132}
133
134/*---------------------------------------------------------------------------*/
135/*---------------------------------------------------------------------------*/
136
139{
140 // In recovery, initialization is considered to take place before
141 // the next iteration, thus using the old values for the time step
142 // and the simulation time.
143
144 ICaseMng* com = subDomain()->caseMng();
145 Int32 opt_iteration = m_global_iteration() - 1;
146 info() << "Initialization to restore the functions of the input data: "
147 << " time=" << m_global_old_time()
148 << " dt=" << m_global_old_deltat()
149 << " iteration=" << opt_iteration;
150 com->updateOptions(m_global_old_time(), m_global_old_deltat(), opt_iteration);
151
152 _masterContinueInit();
153}
154
155/*---------------------------------------------------------------------------*/
156/*---------------------------------------------------------------------------*/
157
163
164/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
169{
172
173 info() << " ";
174 info(0) << "***"
175 << " ITERATION " << Trace::Width(8) << m_global_iteration()
176 << " TIME " << Trace::Width(digit) << Trace::Precision(precision, m_global_time(), true)
177 << " LOOP " << Trace::Width(8) << m_nb_loop
178 << " DELTAT " << Trace::Width(digit) << Trace::Precision(precision, m_global_deltat(), true)
179 << " ***";
180}
181
182/*---------------------------------------------------------------------------*/
183/*---------------------------------------------------------------------------*/
184
187{
188 // First loop, initializes the time and displays info
189 // on consumption
190 if (m_is_first_loop) {
191 info() << "Information on consumption (unit:second): Con(R=...,I=...,C=...)";
192 info() << " R -> consumption in real time (clock) since the beginning of the computation";
193 info() << " I -> real time (clock) spent during the last iteration";
194 info() << " C -> consumption in CPU time since the beginning of the computation";
195 info() << "Information on memory consumption (unit: Mo): Mem=(X,m=X1:R1,M=X2:R2,avg=Z)";
196 info() << " X -> memory consumption of the process";
197 info() << " X1 -> memory consumption of the least memory hungry process and R1 is its rank";
198 info() << " X2 -> memory consumption of the most memory hungry process and R2 is its rank";
199 info() << " Z -> average memory consumption of all process";
200 }
201
202 ++m_nb_loop;
203
204 // Updates the dataset options that depend on a marching table.
205 ICaseMng* com = subDomain()->caseMng();
207
208 Real mem_used = platform::getMemoryUsed();
209
211
213
214 // Infos for curves
215 m_thm_mem_used = mem_used;
216
217 // Adds the deltat to the current time
218 //info() << "[ModuleMaster::timeLoopBegin] Add deltat to the current time";
220
221 m_thm_global_time = m_global_time();
222 //thm->addValue(m_global_time.name(),m_global_time());
223
224 //info() << "[ModuleMaster::timeLoopBegin] breakpoint_requested?";
226
227 // It is absolutely necessary that this value is the same for all subdomains
228 Real cpu_time = (Real)platform::getCPUTime();
229 Real elapsed_time = platform::getRealTime();
230 {
231 Real values[3];
232 ArrayView<Real> vals(3, values);
233 values[0] = cpu_time;
234 values[1] = elapsed_time;
235 values[2] = (hyoda) ? hyoda->loopbreak(subDomain()) : 0.0;
237 cpu_time = values[0];
238 elapsed_time = values[1];
239 if (hyoda && values[2] > 0.0)
240 hyoda->hook(subDomain(), values[2]);
241 }
242 if (m_is_first_loop) {
243 m_old_cpu_time = cpu_time;
244 m_old_elapsed_time = elapsed_time;
245 }
246 Real diff_cpu = (cpu_time - m_old_cpu_time) / CLOCKS_PER_SEC;
247 Real diff_elapsed = (elapsed_time - m_old_elapsed_time);
248 m_global_old_cpu_time = diff_cpu;
249 m_global_old_elapsed_time = diff_elapsed;
252
253 m_thm_diff_cpu = diff_cpu;
254 m_thm_global_cpu_time = m_global_cpu_time();
255 m_thm_diff_elapsed = diff_elapsed;
256 m_thm_global_elapsed_time = m_global_elapsed_time();
257
258 m_old_cpu_time = cpu_time;
259 m_old_elapsed_time = elapsed_time;
260
262
263 Real mem_sum = 0.0;
264 Real mem_min = 0.0;
265 Real mem_max = 0.0;
266 Int32 mem_min_rank = 0;
267 Int32 mem_max_rank = 0;
268 pm->computeMinMaxSum(mem_used, mem_min, mem_max, mem_sum, mem_min_rank, mem_max_rank);
269 // Truncate to millisecond
270 Int64 i_elapsed = (Int64)(m_global_elapsed_time() * 1000.0);
271 Int64 i_diff_elapsed = (Int64)(diff_elapsed * 1000.0);
272 Int64 i_cpu = (Int64)(m_global_cpu_time() * 1000.0);
273 info(1) << "Date: " << platform::getCurrentDateTime()
274 << " Conso=(R=" << (((Real)i_elapsed) / 1000.0)
275 << ",I=" << (((Real)i_diff_elapsed) / 1000.0)
276 << ",C=" << ((Real)i_cpu / 1000.0)
277 << ") Mem=(" << (Int64)(mem_used / 1e6)
278 << ",m=" << (Int64)(mem_min / 1e6)
279 << ":" << mem_min_rank
280 << ",M=" << (Int64)(mem_max / 1e6)
281 << ":" << mem_max_rank
282 << ",avg=" << (Int64)(mem_sum / 1e6) / pm->commSize()
283 << ")";
284
285 _masterBeginLoop();
286 m_is_first_loop = false;
287 m_has_thm_dump_at_iteration = false;
288}
289
290/*---------------------------------------------------------------------------*/
291/*---------------------------------------------------------------------------*/
292
295{
296 _masterEndLoop();
297
298 // Performs curve outputs
299 // Since it is possible to disable curve outputs
300 // at a given iteration, the outputs must be done at the end of the iteration
301 // and not at the beginning to allow other modules to enable or not
302 // the outputs. It is also possible for a user code to call
303 // this method explicitly so that it performs the outputs when it
304 // wishes during the iteration.
306
307 // Increments the iteration counter
309
310 if (subDomain()->timeLoopMng()->finalTimeReached()) {
311 info() << "===============================================================";
312 info() << "====== END OF COMPUTATION REACHED... =======================";
313 info() << "===============================================================";
314 }
315}
316
317/*---------------------------------------------------------------------------*/
318/*---------------------------------------------------------------------------*/
319
322{
323 if (m_has_thm_dump_at_iteration)
324 return;
325
326 // If this method is called at the end of the iteration, then the
327 // cpu time (m_thm_diff_cpu) and elapsed (m_thm_global_elapsed_time)
328 // are not good because they were calculated at the beginning of the iteration and thus
329 // they are not good. We recalculate them therefore by taking care
330 // not to update the m_global* variables to avoid any
331 // inconsistency because these values are not synchronized between all
332 // subdomains (and furthermore this method is not always
333 // called)
334
335 Real cpu_time = (Real)platform::getCPUTime();
336 Real elapsed_time = platform::getRealTime();
337 Real diff_cpu = (cpu_time - m_old_cpu_time) / 1000000.0;
338 Real diff_elapsed = (elapsed_time - m_old_elapsed_time);
339 Real mem_used = platform::getMemoryUsed();
340 Real global_cpu_time = diff_cpu + m_global_cpu_time();
341 Real global_elapsed_time = diff_elapsed + m_global_elapsed_time();
342
344 thm->addValue("TotalMemory", mem_used);
345 thm->addValue("CpuTime", diff_cpu);
346 thm->addValue("GlobalCpuTime", global_cpu_time);
347 thm->addValue("ElapsedTime", diff_elapsed);
348 thm->addValue("GlobalElapsedTime", global_elapsed_time);
349 thm->addValue(m_global_time.name(), m_thm_global_time);
350 m_has_thm_dump_at_iteration = true;
351
352 Int64 i_elapsed = (Int64)(global_elapsed_time * 1000.0);
353 Int64 i_diff_elapsed = (Int64)(diff_elapsed * 1000.0);
354 Int64 i_cpu = (Int64)(global_cpu_time * 1000.0);
355
356 info(4) << "EndIter: Date: " << platform::getCurrentDateTime()
357 << " Conso=(R=" << (((Real)i_elapsed) / 1000.0)
358 << ",I=" << (((Real)i_diff_elapsed) / 1000.0)
359 << ",C=" << ((Real)i_cpu / 1000.0)
360 << ") Mem=(" << (Int64)(mem_used / 1e6)
361 << ")";
362}
363
364/*---------------------------------------------------------------------------*/
365/*---------------------------------------------------------------------------*/
366
367/*---------------------------------------------------------------------------*/
368/*---------------------------------------------------------------------------*/
369
375
376/*---------------------------------------------------------------------------*/
377/*---------------------------------------------------------------------------*/
378
379void ModuleMaster::
380_masterBeginLoop()
381{
382 for (Integer i = 0, is = m_timeloop_services.size(); i < is; ++i) {
384 service->onTimeLoopBeginLoop();
385 }
386}
387
388/*---------------------------------------------------------------------------*/
389/*---------------------------------------------------------------------------*/
390
391void ModuleMaster::
392_masterEndLoop()
393{
394 for (Integer i = 0, is = m_timeloop_services.size(); i < is; ++i) {
395 ITimeLoopService* service = m_timeloop_services[i];
396 service->onTimeLoopEndLoop();
397 }
398}
399
400/*---------------------------------------------------------------------------*/
401/*---------------------------------------------------------------------------*/
402
403void ModuleMaster::
404_masterStartInit()
405{
406 for (Integer i = 0, is = m_timeloop_services.size(); i < is; ++i) {
407 ITimeLoopService* service = m_timeloop_services[i];
408 service->onTimeLoopStartInit();
409 }
410}
411
412/*---------------------------------------------------------------------------*/
413/*---------------------------------------------------------------------------*/
414
415void ModuleMaster::
416_masterContinueInit()
417{
418 for (Integer i = 0, is = m_timeloop_services.size(); i < is; ++i) {
419 ITimeLoopService* service = m_timeloop_services[i];
420 service->onTimeLoopContinueInit();
421 }
422}
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426
427void ModuleMaster::
428_masterLoopExit()
429{
430 for (Integer i = 0, is = m_timeloop_services.size(); i < is; ++i) {
431 ITimeLoopService* service = m_timeloop_services[i];
432 service->onTimeLoopExit();
433 }
434}
435
436/*---------------------------------------------------------------------------*/
437/*---------------------------------------------------------------------------*/
438
439void ModuleMaster::
440_masterMeshChanged()
441{
442 for (Integer i = 0, is = m_timeloop_services.size(); i < is; ++i) {
443 ITimeLoopService* service = m_timeloop_services[i];
444 service->onTimeLoopMeshChanged();
445 }
446}
447
448/*---------------------------------------------------------------------------*/
449/*---------------------------------------------------------------------------*/
450
451void ModuleMaster::
452_masterRestore()
453{
454 for (Integer i = 0, is = m_timeloop_services.size(); i < is; ++i) {
455 ITimeLoopService* service = m_timeloop_services[i];
456 service->onTimeLoopRestore();
457 }
458}
459
460/*---------------------------------------------------------------------------*/
461/*---------------------------------------------------------------------------*/
462
463} // namespace Arcane
464
465/*---------------------------------------------------------------------------*/
466/*---------------------------------------------------------------------------*/
ISubDomain * subDomain() const override
Sub-domain associated with the module.
AbstractModule(const ModuleBuildInfo &)
Constructor from a ModuleBuildInfo.
IParallelMng * parallelMng() const override
Message passing parallelism manager.
Modifiable view of an array of type T.
VariableScalarInt32 m_global_iteration
Current iteration.
VariableScalarReal m_global_elapsed_time
Clock time used (in seconds).
VariableScalarReal m_global_cpu_time
CPU time used (in seconds).
VariableScalarReal m_global_old_deltat
Delta T at the time previous to the global time.
VariableScalarReal m_global_old_elapsed_time
Previous clock time used (in seconds).
VariableScalarReal m_global_time
Current time.
CommonVariables(IModule *c)
Constructs the references of the common variables for the module c.
VariableScalarReal m_global_old_cpu_time
Previous CPU time used (in seconds).
VariableScalarReal m_global_old_time
Time previous to the current time.
VariableScalarReal m_global_deltat
Global Delta T.
Information about the floating-point type.
Definition Limits.h:49
Case manager interface.
Definition ICaseMng.h:57
virtual void updateOptions(Real current_time, Real current_deltat, Integer current_iteration)=0
Updates the options based on a time-marching table.
static const char *const WComputeLoop
called during the calculation loop
Definition IEntryPoint.h:43
static const char *const WStartInit
called during new case initialization
Definition IEntryPoint.h:51
static const char *const WRestore
called to restore variables during a rollback
Definition IEntryPoint.h:53
@ PAutoLoadEnd
Automatically loaded at the end. This means that a module possessing an entry point with this propert...
Definition IEntryPoint.h:81
@ PAutoLoadBegin
Automatically loaded at the beginning. This means that a module possessing an entry point with this p...
Definition IEntryPoint.h:74
static const char *const WOnMeshChanged
called after a mesh change
Definition IEntryPoint.h:55
static const char *const WContinueInit
called during continuation initialization
Definition IEntryPoint.h:49
static const char *const WInit
called during initialization
Definition IEntryPoint.h:47
Interface of the main module.
Interface of a hybrid debugger service.
Interface of the parallelism manager for a subdomain.
virtual void computeMinMaxSum(char val, char &min_val, char &max_val, char &sum_val, Int32 &min_rank, Int32 &max_rank)=0
Calculates the sum, min, and max of a value in one operation.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
Interface of the subdomain manager.
Definition ISubDomain.h:75
virtual ITimeHistoryMng * timeHistoryMng()=0
Returns the history manager.
virtual ICaseMng * caseMng()=0
Returns the dataset manager.
virtual IParallelMng * allReplicaParallelMng() const =0
Returns the parallelism manager for all replicas.
Class managing a history of values.
virtual void addValue(const String &name, Real value, bool end_time=true, bool is_local=false)=0
Adds the value value to the history name.
Interface of a service operating during the time loop.
Information for building a module.
ISubDomain * subDomain() const
Access to the associated subdomain.
void masterInit()
Auto-loaded entry point at the beginning of initialization.
void masterStartInit()
Auto-loaded entry point at the beginning of a new case initialization.
CaseOptionsMain * m_case_options_main
Instance of module options.
bool m_is_first_loop
Indicates if we are in the first execution loop.
Real m_old_cpu_time
CPU time value at the last iteration.
ModuleMaster(const ModuleBuildInfo &)
Constructor.
void dumpStandardCurves() override
Dumps standard curves (CPUTime, ElapsedTime, ...).
Real m_old_elapsed_time
Clock time value at the last iteration.
virtual void timeStepInformation()
Overridable display of time step information.
void timeLoopEnd()
Auto-loaded entry point at the end of the calculation loop iteration.
void timeLoopBegin()
Auto-loaded entry point at the beginning of the calculation loop iteration.
void addTimeLoopService(ITimeLoopService *tls) override
Adds the time loop service.
UniqueArray< ITimeLoopService * > m_timeloop_services
List of time loop services.
virtual void timeIncrementation()
Overridable time step incrementation.
Integer m_nb_loop
Number of calculation loops performed.
~ModuleMaster() override
Destructor.
void masterContinueInit()
Auto-loaded entry point at the beginning of a new case restart.
TraceMessage info() const
Flow for an information message.
Formatting real numbers with a given precision.
Formatting the stream by length.
@ ReduceMax
Maximum of values.
double getMemoryUsed()
Memory used in bytes.
Real getRealTime()
Real time used in seconds.
String getCurrentDateTime()
Current date and time in ISO 8601 format.
Int64 getCPUTime()
CPU time used in microseconds.
IOnlineDebuggerService * getOnlineDebuggerService()
Service used to set up an online debug architecture.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
double Real
Type representing a real number.
void addEntryPoint(ModuleType *module, const char *name, void(ModuleType::*func)(), const String &where=IEntryPoint::WComputeLoop, int property=IEntryPoint::PNone)
Template routine allowing an entry point to be referenced in a module.
Definition EntryPoint.h:174
std::int32_t Int32
Signed integer type of 32 bits.