Arcane  4.2.2.0
User documentation
Loading...
Searching...
No Matches
ArcaneLauncher.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/* ArcaneLauncher.cc (C) 2000-2026 */
9/* */
10/* Class managing the execution launch. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/launcher/ArcaneLauncher.h"
15
16#include "arcane/launcher/IDirectExecutionContext.h"
17#include "arcane/launcher/DirectSubDomainExecutionContext.h"
18#include "arcane/launcher/GeneralHelp.h"
19#include "arcane/launcher/internal/ParamFile.h"
20
21#include "arcane/utils/FatalErrorException.h"
22#include "arcane/utils/PlatformUtils.h"
23#include "arcane/utils/JSONReader.h"
24#include "arcane/utils/Exception.h"
25#include "arcane/utils/ParameterList.h"
26#include "arcane/utils/Ref.h"
28#include "arcane/utils/internal/ParallelLoopOptionsProperties.h"
29#include "arcane/utils/internal/ApplicationInfoProperties.h"
30#include "arcane/core/internal/DotNetRuntimeInitialisationInfoProperties.h"
31#include "arcane/accelerator/core/internal/AcceleratorRuntimeInitialisationInfoProperties.h"
32
33#include "arccore/common/internal/Property.h"
34#include "arccore/common/internal/ParameterListPropertyReader.h"
35#include "arccore/common/internal/JSONPropertyReader.h"
36
37#include "arcane/impl/ArcaneMain.h"
38#include "arcane/impl/ArcaneSimpleExecutor.h"
39
40#include "arcane/core/IDirectSubDomainExecuteFunctor.h"
41
42#include <iomanip>
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
47namespace Arcane
48{
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53namespace
54{
55 bool global_has_init_done = false;
56 bool _checkInitCalled()
57 {
58 if (!global_has_init_done) {
59 std::cerr << "ArcaneLauncher::init() has to be called before";
60 return true;
61 }
62 return false;
63 }
64
65} // namespace
66
67/*---------------------------------------------------------------------------*/
68/*---------------------------------------------------------------------------*/
69
70class DirectExecutionContextImpl
72{
73 public:
74
75 explicit DirectExecutionContextImpl(ArcaneSimpleExecutor* simple_exec)
76 : m_simple_exec(simple_exec)
77 {}
78
79 public:
80
85 ISubDomain* createSequentialSubDomain(const String& case_file_name) override
86 {
87 return m_simple_exec->createSubDomain(case_file_name);
88 }
89 ISubDomain* subDomain() const { return nullptr; }
90
91 private:
92
93 ArcaneSimpleExecutor* m_simple_exec;
94};
95
96/*---------------------------------------------------------------------------*/
97/*---------------------------------------------------------------------------*/
98
99void _checkReadConfigFile(StringView config_file_name)
100{
101 // TODO: in parallel, only one PE should perform the reading.
102 if (config_file_name.empty())
103 return;
104 std::cout << "TRY_READING_CONFIG " << config_file_name << "\n";
105 if (!platform::isFileReadable(config_file_name))
106 return;
108 bool is_bad = platform::readAllFile(config_file_name, false, bytes);
109 if (is_bad)
110 return;
112 app_info.setRuntimeConfigFileContent(bytes);
113 JSONDocument jdoc;
114 jdoc.parse(bytes);
115 JSONValue config = jdoc.root().child("configuration");
116 if (config.null())
117 return;
118 std::cout << "READING CONFIG\n";
119 properties::readFromJSON<ApplicationInfo, ApplicationInfoProperties>(config, app_info);
120}
121
122/*---------------------------------------------------------------------------*/
123/*---------------------------------------------------------------------------*/
124
126run()
127{
128 return ArcaneMain::run();
129}
130
131/*---------------------------------------------------------------------------*/
132/*---------------------------------------------------------------------------*/
133
136{
137 return ArcaneMain::defaultApplicationInfo();
138}
139
140/*---------------------------------------------------------------------------*/
141/*---------------------------------------------------------------------------*/
142
145{
146 return ArcaneMain::defaultDotNetRuntimeInitialisationInfo();
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151
154{
155 return ArcaneMain::defaultAcceleratorRuntimeInitialisationInfo();
156}
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160
163{
164 return ArcaneMain::defaultApplicationBuildInfo();
165}
166
167/*---------------------------------------------------------------------------*/
168/*---------------------------------------------------------------------------*/
169
172{
173 String exe_full_path = platform::getExeFullPath();
174 String exe_dir = platform::getFileDirName(exe_full_path);
175 return exe_dir;
176}
177
178/*---------------------------------------------------------------------------*/
179/*---------------------------------------------------------------------------*/
180
181class DirectCodeFunctor
182: public IFunctor
183{
184 public:
185
186 typedef std::function<int(IDirectExecutionContext*)> OldFunctorType;
187 typedef std::function<int(DirectExecutionContext&)> FunctorType;
188
189 public:
190
191 DirectCodeFunctor(ArcaneSimpleExecutor* x, FunctorType* ft)
192 : m_simple_executor(x)
193 , m_functor(ft)
194 {}
195 DirectCodeFunctor(ArcaneSimpleExecutor* x, OldFunctorType* ft)
196 : m_simple_executor(x)
197 , m_old_functor(ft)
198 {}
199 void executeFunctor() override
200 {
201 DirectExecutionContextImpl direct_context_impl(m_simple_executor);
202 if (m_functor) {
203 DirectExecutionContext direct_context(&direct_context_impl);
204 m_return_value = (*m_functor)(direct_context);
205 }
206 else if (m_old_functor)
207 m_return_value = (*m_old_functor)(&direct_context_impl);
208 }
209 int returnValue() const { return m_return_value; }
210
211 public:
212
213 ArcaneSimpleExecutor* m_simple_executor = nullptr;
214 OldFunctorType* m_old_functor = nullptr;
215 FunctorType* m_functor = nullptr;
216 int m_return_value = 0;
217};
218
219/*---------------------------------------------------------------------------*/
220/*---------------------------------------------------------------------------*/
221// Obsolete
223runDirect(std::function<int(IDirectExecutionContext* c)> func)
224{
225 if (_checkInitCalled())
226 return (-1);
227 int final_return = 0;
228 {
229 ArcaneSimpleExecutor simple_exec;
230 int r = simple_exec.initialize();
231 if (r != 0)
232 return r;
233 // Encapsulates the code in a functor that will handle exceptions. Without
234 // this, in case of an exception and if the calling code does nothing, we
235 // will have a call to std::terminate
236 DirectCodeFunctor direct_functor(&simple_exec, &func);
237 simple_exec.runCode(&direct_functor);
238 final_return = direct_functor.returnValue();
239 }
240 return final_return;
241}
242
243/*---------------------------------------------------------------------------*/
244/*---------------------------------------------------------------------------*/
245
247run(std::function<int(DirectExecutionContext&)> func)
248{
249 if (_checkInitCalled())
250 return (-1);
251
252 int final_return = 0;
253 {
254 ArcaneSimpleExecutor simple_exec;
255 int r = simple_exec.initialize();
256 if (r != 0)
257 return r;
258 // Encapsulates the code in a functor that will handle exceptions. Without
259 // this, in case of an exception and if the calling code does nothing, we
260 // will have a call to std::terminate
261 DirectCodeFunctor direct_functor(&simple_exec, &func);
262 simple_exec.runCode(&direct_functor);
263 final_return = direct_functor.returnValue();
264 }
265 return final_return;
266}
267
268/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
270
271class ArcaneLauncherDirectExecuteFunctor
273{
274 public:
275
276 ArcaneLauncherDirectExecuteFunctor(std::function<int(DirectSubDomainExecutionContext&)> func)
277 : m_function(func)
278 {}
279
280 public:
281
282 int execute() override
283 {
284 if (!m_sub_domain)
285 ARCANE_FATAL("Can not execute 'IDirectSubDomainExecuteFunctor' without sub domain");
286 DirectSubDomainExecutionContext direct_context(m_sub_domain);
287 return m_function(direct_context);
288 }
289 void setSubDomain(ISubDomain* sd) override { m_sub_domain = sd; }
290
291 private:
292
293 std::function<int(DirectSubDomainExecutionContext&)> m_function;
294
295 public:
296
297 ISubDomain* m_sub_domain = nullptr;
298};
299
300/*---------------------------------------------------------------------------*/
301/*---------------------------------------------------------------------------*/
302
304run(std::function<int(DirectSubDomainExecutionContext&)> func)
305{
306 if (_checkInitCalled())
307 return (-1);
308
309 ArcaneLauncherDirectExecuteFunctor direct_exec(func);
310 // In direct execution, by default there is no configuration file for the
311 // code. If the user has not provided a configuration file, we set it to
312 // the null string.
314 // The default is the empty string. The null string explicitly indicates
315 // that no configuration file is desired
316 if (config_file.empty())
318 int r = ArcaneMain::_internalRun(&direct_exec);
319 return r;
320}
321
322/*---------------------------------------------------------------------------*/
323/*---------------------------------------------------------------------------*/
324
325namespace
326{
327 class MyVisitor
328 : public properties::IPropertyVisitor
329 {
330 public:
331
332 void visit(const properties::IPropertySetting* s) override
333 {
334 if (!s->commandLineArgument().null()) {
335 std::cout << "ARG:" << std::setw(30) << s->commandLineArgument()
336 << " " << s->description() << "\n";
337 }
338 }
339 };
340
341 void
342 _listPropertySettings()
343 {
344 using namespace Arcane::properties;
345 MyVisitor my_visitor;
346 visitAllRegisteredProperties(&my_visitor);
347 }
348} // namespace
349
351init(const CommandLineArguments& args)
352{
353 try {
354 if (global_has_init_done)
355 ARCANE_FATAL("ArcaneLauncher::init() has already been called");
356 global_has_init_done = true;
357 auto& application_info = applicationInfo();
358 application_info.setCommandLineArguments(args);
359 bool do_list = false;
360 if (do_list)
361 _listPropertySettings();
363 String runtime_config_file_name = cargs.getParameter("RuntimeConfigFile");
364 if (!runtime_config_file_name.empty())
365 _checkReadConfigFile(runtime_config_file_name);
366
367 String param_file_name = cargs.getParameter("ParamFile");
368 if (!param_file_name.empty()) {
369 String variation_param_file_name = cargs.getParameter("Variation");
370 ParamFile::editParams(param_file_name, variation_param_file_name);
371 }
372
373
374 properties::readFromParameterList<ApplicationInfo, ApplicationInfoProperties>(args.parameters(), application_info);
376 properties::readFromParameterList<DotNetRuntimeInitialisationInfo, DotNetRuntimeInitialisationInfoProperties>(args.parameters(), dotnet_info);
378 properties::readFromParameterList<AcceleratorRuntimeInitialisationInfo, Accelerator::AcceleratorRuntimeInitialisationInfoProperties>(args.parameters(), accelerator_info);
379 ParallelLoopOptions loop_options;
380 properties::readFromParameterList<ParallelLoopOptions, ParallelLoopOptionsProperties>(args.parameters(), loop_options);
382 }
383 catch (const Exception& ex) {
384 cerr << ex << '\n';
385 cerr << "** (ArcaneLauncher) Can't continue with the execution.\n";
386 throw;
387 }
388}
389
390/*---------------------------------------------------------------------------*/
391/*---------------------------------------------------------------------------*/
392
395{
396 return global_has_init_done;
397}
398
399/*---------------------------------------------------------------------------*/
400/*---------------------------------------------------------------------------*/
401
404{
405 ArcaneMain::setDefaultMainFactory(mf);
406}
407
408/*---------------------------------------------------------------------------*/
409/*---------------------------------------------------------------------------*/
410
411void ArcaneLauncher::
412_initStandalone()
413{
414 if (!global_has_init_done)
415 ARCANE_FATAL("ArcaneLauncher::init() has to be called before");
416 // This is necessary to potentially dynamically load the runtime associated
417 // with accelerators
418 ArcaneMain::_initRuntimes();
419}
420
421/*---------------------------------------------------------------------------*/
422/*---------------------------------------------------------------------------*/
423
426{
427 _initStandalone();
428 return {};
429}
430
431/*---------------------------------------------------------------------------*/
432/*---------------------------------------------------------------------------*/
433
434StandaloneSubDomain ArcaneLauncher::
435createStandaloneSubDomain(const String& case_file_name, Span<const std::byte> file_content)
436{
437 _initStandalone();
438 StandaloneSubDomain s;
439 s._initUniqueInstance(case_file_name, file_content);
440 return s;
441}
442
443/*---------------------------------------------------------------------------*/
444/*---------------------------------------------------------------------------*/
445
446void ArcaneLauncher::
447_notifyRemoveStandaloneSubDomain()
448{
449}
450
451/*---------------------------------------------------------------------------*/
452/*---------------------------------------------------------------------------*/
453
459
460/*---------------------------------------------------------------------------*/
461/*---------------------------------------------------------------------------*/
462
464printHelp()
465{
466 if (applicationInfo().commandLineArguments().needHelp()) {
467 GeneralHelp::printHelp();
468 return true;
469 }
470 return false;
471}
472
473/*---------------------------------------------------------------------------*/
474/*---------------------------------------------------------------------------*/
475
476} // End namespace Arcane
477
478/*---------------------------------------------------------------------------*/
479/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Classes, Types, and macros for managing concurrency.
Information for constructing an instance of IApplication.
String configFileName() const
Name of the code configuration file.
void setConfigFileName(const String &name)
Sets the code configuration file.
Application information.
const CommandLineArguments & commandLineArguments() const
Command line arguments.
int execute() override
Executes the functor's operation.
void setSubDomain(ISubDomain *sd) override
Positions the associated subdomain. This method must be called before execute().
static StandaloneAcceleratorMng createStandaloneAcceleratorMng()
Creates a standalone implementation to manage accelerators.
static int run()
Entry point of the executable in Arcane.
static String getExeDirectory()
Full name of the directory where the executable is located.
static DotNetRuntimeInitialisationInfo & dotNetRuntimeInitialisationInfo()
Information for '.Net' runtime initialization.
static bool needHelp()
Requests help with the "--help" or "-h" option.
static void init(const CommandLineArguments &args)
Positions information from command-line arguments and initializes the launcher.
static ApplicationBuildInfo & applicationBuildInfo()
Application execution parameter information.
static StandaloneSubDomain createStandaloneSubDomain(const String &case_file_name, Span< const std::byte > file_content={})
Creates a standalone implementation to manage a subdomain.
static bool isInitialized()
Indicates if init() has already been called.
static bool printHelp()
Display of generic Arcane help.
static ApplicationInfo & applicationInfo()
Application information.
static AcceleratorRuntimeInitialisationInfo & acceleratorRuntimeInitialisationInfo()
Information for accelerator initialization.
static int runDirect(std::function< int(IDirectExecutionContext *)> func)
static void setDefaultMainFactory(IMainFactory *mf)
Positions the default factory for creating the different managers.
const ParameterList & parameters() const
List of parameters.
bool needHelp() const
Method to determine if the user requested help on the command line.
String getParameter(const String &param_name) const
Retrieves the parameter with name param_name.
void executeFunctor() override
Executes the associated method.
ISubDomain * createSequentialSubDomain(const String &case_file_name) override
Create a sequential sub-domain with the dataset file named case_file_name.
ISubDomain * createSequentialSubDomain() override
Create a sequential sub-domain without a dataset.
Direct execution context with subdomain creation.
Information for the initialization of the '.Net' runtime.
Interface of the subdomain manager.
Definition ISubDomain.h:78
void parse(Span< const Byte > bytes, Int16 flags=ParseNoFlags)
Reads the file in UTF-8 format.
JSONValue child(StringView name) const
Child value with name name. Returns a null value if not found.
Execution options for a parallel loop in multi-threading.
View of an array of elements of type T.
Definition Span.h:633
Standalone implementation of 'IAcceleratorMng.h'.
View of a UTF-8 character string.
Definition StringView.h:44
bool empty() const
True if the string is empty (null or "").
Definition String.cc:317
static void setDefaultParallelLoopOptions(const ParallelLoopOptions &v)
Sets the default parallel loop execution options.
1D data vector with value semantics (STL style).
String getFileDirName(const String &file_name)
Returns the directory name of a file.
bool isFileReadable(const String &file_name)
Checks if the file file_name is accessible and readable.
String getExeFullPath()
Returns the full name with the executable path.
bool readAllFile(StringView filename, bool is_binary, ByteArray &out_bytes)
Reads the content of a file and stores it in out_bytes.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --