Arcane  v4.1.2.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
CaseMng.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/* CaseMng.cc (C) 2000-2025 */
9/* */
10/* Classe gérant les options du jeu de données. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/PlatformUtils.h"
15#include "arcane/utils/List.h"
16#include "arcane/utils/ValueConvert.h"
17#include "arcane/utils/Deleter.h"
18#include "arcane/utils/StringBuilder.h"
19#include "arcane/utils/ITraceMng.h"
20#include "arcane/utils/TraceAccessor.h"
21#include "arcane/utils/FatalErrorException.h"
22#include "arcane/utils/OStringStream.h"
23#include "arcane/utils/ScopedPtr.h"
24#include "arcane/utils/ApplicationInfo.h"
25#include "arcane/utils/NotImplementedException.h"
26#include "arcane/utils/CriticalSection.h"
27#include "arcane/utils/CommandLineArguments.h"
28#include "arcane/utils/internal/ParameterListWithCaseOption.h"
29
30#include "arcane/core/ISubDomain.h"
31#include "arcane/core/IApplication.h"
32#include "arcane/core/IParallelMng.h"
33#include "arcane/core/IParallelSuperMng.h"
34#include "arcane/core/ICaseMng.h"
35#include "arcane/core/IModule.h"
36#include "arcane/core/CaseOptions.h"
37#include "arcane/core/XmlNode.h"
38#include "arcane/core/XmlNodeList.h"
39#include "arcane/core/XmlNodeIterator.h"
40#include "arcane/core/ICaseDocument.h"
41#include "arcane/core/ICaseFunctionProvider.h"
42#include "arcane/core/CaseNodeNames.h"
43#include "arcane/core/ISession.h"
44#include "arcane/core/CaseTable.h"
45#include "arcane/core/IMainFactory.h"
46#include "arcane/core/IIOMng.h"
47#include "arcane/core/ServiceFinder2.h"
48#include "arcane/core/ObservablePool.h"
49#include "arcane/core/ICaseDocumentVisitor.h"
50#include "arcane/core/ServiceBuilder.h"
51#include "arcane/core/internal/ICaseMngInternal.h"
52
53#include "arcane/impl/CaseDocumentLangTranslator.h"
54
55/*---------------------------------------------------------------------------*/
56/*---------------------------------------------------------------------------*/
57
58namespace Arcane
59{
60
61/*---------------------------------------------------------------------------*/
62/*---------------------------------------------------------------------------*/
63
64extern "C++" std::unique_ptr<ICaseDocumentVisitor>
65createPrintCaseDocumentVisitor(ITraceMng* tm,const String& lang);
66
67extern "C++" ICaseDocumentFragment*
68arcaneCreateCaseDocumentFragment(ITraceMng* tm,IXmlDocumentHolder* document);
69
70/*---------------------------------------------------------------------------*/
71/*---------------------------------------------------------------------------*/
75class CaseMng
77, public ICaseMng
78, public ICaseMngInternal
79, public TraceAccessor
80{
81 ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS();
82
83 private:
84
85 class OptionsReader
86 {
87 public:
88 OptionsReader(ICaseMng*) {}
89 void read(bool is_phase1);
90 void addOption(ICaseOptions* o) { m_options.add(o); }
91 private:
93 void _read(bool is_phase1);
94 void _searchInvalidOptions();
95 };
96 private:
97
98 class ErrorInfo
99 {
100 public:
101 explicit ErrorInfo(const String& error_message)
102 : m_has_error(true), m_error_message(error_message){}
103 ErrorInfo() : m_has_error(false){}
104 public:
105 bool hasError() const { return m_has_error; }
106 const String& errorMessage() const { return m_error_message; }
107 private:
108 bool m_has_error;
109 String m_error_message;
110 };
111
116 class CaseOptionsFilterUsed
117 {
118 public:
119 explicit CaseOptionsFilterUsed(const CaseOptionsList& opt_list)
120 : m_begin(opt_list.begin()), m_end(opt_list.end()){}
121 public:
122 auto begin() const { return m_begin; }
123 auto end() const { return m_end; }
124 void operator++()
125 {
126 bool do_continue = true;
127 do {
128 ++m_begin;
129 if (m_begin >= m_end)
130 return;
131 ICaseOptions* co = *m_begin;
132 IModule* md = co->caseModule();
133 do_continue = (md && !md->used());
134 } while (do_continue);
135 }
136 private:
137 CaseOptionsList::const_iterator m_begin;
138 CaseOptionsList::const_iterator m_end;
139 };
140
141 public:
142
143 explicit CaseMng(ISubDomain*);
144 ~CaseMng() override;
145
146 public:
147
149 IMeshMng* meshMng() const override { return m_sub_domain->meshMng(); }
150 ISubDomain* subDomain() override { return m_sub_domain; }
151 IApplication* application() override { return m_sub_domain->application(); }
152 IPhysicalUnitSystem* physicalUnitSystem() const override { return m_sub_domain->physicalUnitSystem(); }
153 ICaseDocument* caseDocument() override { return m_case_document.get(); }
155 {
157 if (doc)
158 return doc->fragment();
159 return nullptr;
160 }
161 ICaseDocument* readCaseDocument(const String& filename,ByteConstArrayView bytes) override;
162
163 void readFunctions() override;
164 void readOptions(bool is_phase1) override;
165 void printOptions() override;
166 void registerOptions(ICaseOptions*) override;
167 void unregisterOptions(ICaseOptions*) override;
168 ICaseFunction* findFunction(const String& name) const override;
169 void updateOptions(Real current_time,Real current_deltat,Integer current_iteration) override;
170 CaseFunctionCollection functions() override { return m_functions; }
171
172 void removeFunction(ICaseFunction* func,bool dofree) override;
173 void removeFunction(ICaseFunction* func) override;
174 void addFunction(ICaseFunction* func) override
175 {
176 addFunction(makeRef(func));
177 }
178 void addFunction(Ref<ICaseFunction> func) override;
179
181
182 void setTreatWarningAsError(bool v) override { m_treat_warning_as_error = v; }
183 bool isTreatWarningAsError() const override { return m_treat_warning_as_error; }
184
185 void setAllowUnkownRootElelement(bool v) override { m_allow_unknown_root_element = v; }
186 bool isAllowUnkownRootElelement() const override { return m_allow_unknown_root_element; }
187
189 {
190 return m_observables[type];
191 }
192
193 Ref<ICaseFunction> findFunctionRef(const String& name) const;
194
195 Ref<ICaseMng> toReference() override { return makeRef<ICaseMng>(this); }
196
197 ICaseMngInternal* _internalImpl() override { return this; }
198
200
201 void internalReadOneOption(ICaseOptions* opt, bool is_phase1) override;
203 {
204 return arcaneCreateCaseDocumentFragment(traceMng(),document);
205 }
206 const ParameterListWithCaseOption& parameters() const { return m_parameters; }
208
209 public:
210
211 String msgClassName() const { return "CaseMng"; }
212
213 private:
214
216 ScopedPtrT<ICaseDocument> m_case_document;
217 CaseFunctionList m_functions;
219 List<CaseOptionBase*> m_options_with_function;
220 bool m_treat_warning_as_error = false;
221 bool m_allow_unknown_root_element = true;
224 bool m_is_function_read = false;
225 Ref<ICaseFunctionDotNetProvider> m_dotnet_provider;
226 ParameterListWithCaseOption m_parameters;
227
228 private:
229
230 ErrorInfo _readOneTable(const XmlNode& func_elem);
231 ErrorInfo _checkValidFunction(const XmlNode& func_elem,CaseFunctionBuildInfo& cfbi);
232 void _readOptions(bool is_phase1);
233 void _readFunctions();
234 void _readCaseDocument(const String& filename,ByteConstArrayView bytes);
235 void _printErrors(ICaseDocumentFragment* doc,bool is_phase1);
236 void _checkTranslateDocument();
237 void _removeFunction(ICaseFunction* func,bool do_delete);
239 ICaseDocument* _noNullCaseDocument()
240 {
241 ICaseDocument* doc = m_case_document.get();
243 return doc;
244 }
245 void _readOneDotNetFunction(const String& assembly_name,const String& class_name);
246};
247
248/*---------------------------------------------------------------------------*/
249/*---------------------------------------------------------------------------*/
250
251void CaseMng::OptionsReader::
252read(bool is_phase1)
253{
254 _read(is_phase1);
255 if (is_phase1)
256 _searchInvalidOptions();
257}
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
261
262void CaseMng::OptionsReader::
263_read(bool is_phase1)
264{
265 auto read_phase = (is_phase1) ? eCaseOptionReadPhase::Phase1 : eCaseOptionReadPhase::Phase2;
266 for( ICaseOptions* co : m_options){
267 co->read(read_phase);
268 }
269}
270
271/*---------------------------------------------------------------------------*/
272/*---------------------------------------------------------------------------*/
273
274void CaseMng::OptionsReader::
275_searchInvalidOptions()
276{
277 // Cherche les éléments du jeu de données qui ne correspondent pas
278 // à une option connue.
279 XmlNodeList invalid_elems;
280 for( ICaseOptions* co : m_options)
281 co->addInvalidChildren(invalid_elems);
282}
283
284/*---------------------------------------------------------------------------*/
285/*---------------------------------------------------------------------------*/
286
287CaseMng::
288CaseMng(ISubDomain* sub_domain)
289: TraceAccessor(sub_domain->traceMng())
290, m_sub_domain(sub_domain)
291, m_treat_warning_as_error(false)
292{
293 if (!platform::getEnvironmentVariable("ARCANE_STRICT_CASEOPTION").null())
294 m_treat_warning_as_error = true;
295
298
299 // Recopie dans \a m_parameters les arguments de la ligne de commande
300 // qui pourraient surcharger les valeurs du jeu de données
301 m_parameters.addParameters(sub_domain->application()->applicationInfo().commandLineArguments().parameters());
302}
303
304/*---------------------------------------------------------------------------*/
305/*---------------------------------------------------------------------------*/
306
307CaseMng::
308~CaseMng()
309{
310}
311
312/*---------------------------------------------------------------------------*/
313/*---------------------------------------------------------------------------*/
314
315/*---------------------------------------------------------------------------*/
316/*---------------------------------------------------------------------------*/
317
318extern "C++" ICaseMng*
319arcaneCreateCaseMng(ISubDomain* mng)
320{
321 return new CaseMng(mng);
322}
323
324/*---------------------------------------------------------------------------*/
325/*---------------------------------------------------------------------------*/
326
328readOptions(bool is_phase1)
329{
330 Trace::Setter mci(traceMng(),msgClassName());
331
332 ICaseDocumentFragment* doc = _noNullCaseDocument()->fragment();
333 if (is_phase1)
334 info() << "Reading the input data (phase1): language '"
335 << doc->language() << "', "
336 << m_case_options_list.count() << " input data.";
337 else
338 info() << "Reading the input data (phase2)";
339
340 if (is_phase1){
342 }
343
344 if (is_phase1)
346
347 // Notifie du début de lecture des options.
348 if (is_phase1)
349 m_observables[eCaseMngEventType::BeginReadOptionsPhase1]->notifyAllObservers();
350 else
351 m_observables[eCaseMngEventType::BeginReadOptionsPhase2]->notifyAllObservers();
352
353 _readOptions(is_phase1);
354 _printErrors(doc,is_phase1);
355
356 _checkTranslateDocument();
357}
358
359/*---------------------------------------------------------------------------*/
360/*---------------------------------------------------------------------------*/
361
362void CaseMng::
363_checkTranslateDocument()
364{
365 // Si demandé, écrit un fichier contenant la traduction dans le langage spécifié
366 // de chaque élément du jeu de données.
367 String tr_lang = platform::getEnvironmentVariable("ARCANE_TRANSLATE_CASEDOCUMENT");
368 if (!tr_lang.null()){
369 info() << "Generating translation for case file to lang=" << tr_lang;
371 String convert_string = translator.translate(this,tr_lang);
372 {
373 std::ofstream ofile("convert_info.txt");
374 convert_string.writeBytes(ofile);
375 }
376 }
377}
378
379/*---------------------------------------------------------------------------*/
380/*---------------------------------------------------------------------------*/
381
382void CaseMng::
383_printErrors(ICaseDocumentFragment* doc,bool is_phase1)
384{
385 //ICaseDocumentFragment* doc = _noNullCaseDocument()->fragment();
386
387 // Affiche les avertissements mais uniquement lors de la phase2 pour les avoir
388 // tous en une fois (certains avertissements ne sont générés que lors de la phase2)
389 if (!m_treat_warning_as_error){
390 if (!is_phase1){
391 if (doc->hasWarnings()){
392 OStringStream ostr;
393 doc->printWarnings(ostr());
394 pwarning() << "The input data are not coherent:\n\n" << ostr.str();
395 }
396 }
397 }
398 bool has_error = doc->hasError();
399 if (doc->hasWarnings() && m_treat_warning_as_error && !is_phase1)
400 has_error = true;
401
402 if (has_error){
403 OStringStream ostr;
404 if (m_treat_warning_as_error && doc->hasWarnings())
405 doc->printWarnings(ostr());
406 doc->printErrors(ostr());
407 ARCANE_FATAL("Input data are invalid:\n\n{0}",ostr.str());
408 }
409}
410
411/*---------------------------------------------------------------------------*/
412/*---------------------------------------------------------------------------*/
413
416{
418 return;
419
420 Trace::Setter mci(traceMng(),msgClassName());
421
422 // Enregistre les services fournissant les fonctions
423 {
425 ISubDomain* sd = subDomain();
426 FinderType finder(sd->application(),sd);
427 const Array<FinderType::FactoryType*>& factories = finder.factories();
428 info() << "NB_CASE_FUNCTION_PROVIDER_FACTORY = " << factories.size();
429 for( const auto& factory : factories ){
430 auto cfp = factory->createServiceReference(ServiceBuildInfoBase(sd));
431 if (cfp.get()){
432 info() << "FOUND CASE FUNCTION PROVIDER (V2)!";
433 cfp->registerCaseFunctions(this);
434 }
435 }
436 }
437
438 _readFunctions();
439
440 m_is_function_read = true;
441}
442
443/*---------------------------------------------------------------------------*/
444/*---------------------------------------------------------------------------*/
445
448{
449 Trace::Setter mci(traceMng(),msgClassName());
450
451 log() << "Register case option <" << co->rootTagName() << ">";
452 m_case_options_list.add(co);
453}
454
455/*---------------------------------------------------------------------------*/
456/*---------------------------------------------------------------------------*/
457
460{
461 m_case_options_list.remove(co);
462}
463
464/*---------------------------------------------------------------------------*/
465/*---------------------------------------------------------------------------*/
466
467void CaseMng::
468_readFunctions()
469{
470 bool has_error = false;
471
472 // Lecture des fonctions
473
474 ICaseDocumentFragment* doc = _noNullCaseDocument()->fragment();
475 XmlNode case_root_elem = doc->rootElement();
476
477 CaseNodeNames* cnn = doc->caseNodeNames();
478
479 // Récupère la liste des tables de marche.
480 XmlNode funcs_elem = case_root_elem.child(cnn->functions);
481 XmlNodeList functions_elem = funcs_elem.children();
482
483 String ustr_table(cnn->function_table);
484 String ustr_script(cnn->function_script);
485
486 if (functions_elem.empty())
487 return;
488
489 for( XmlNode node : functions_elem ){
490 bool is_bad = false;
491 if (node.type()!=XmlNode::ELEMENT)
492 continue;
493 if (node.isNamed(ustr_table)){
494 ErrorInfo err_info = _readOneTable(node);
495 if (err_info.hasError()){
496 is_bad = true;
497 String table_name = node.attrValue(cnn->name_attribute);
498 if (table_name.null())
499 error() << " Error in element '" << node.xpathFullName() << "' : "
500 << err_info.errorMessage();
501 else
502 error() << " Error in table named '" << table_name << "' : "
503 << err_info.errorMessage();
504 }
505 }
506 else if (node.isNamed("external-assembly")){
507 String assembly_name = node.expectedChild("assembly-name").value();
508 String class_name = node.expectedChild("class-name").value();
509 _readOneDotNetFunction(assembly_name,class_name);
510 }
511 else
512 warning() << "Unknown node in functions: " << node.xpathFullName();
513 has_error |= is_bad;
514 }
515
516 if (has_error)
517 ARCANE_FATAL("Error while reading the functions");
518
519 // Affiche des informations sur le nombre de tables et leur nombre
520 // d'éléments
521 log() << "Number of functions: " << m_functions.count();
522 for( auto& icf_ref : m_functions ){
523 auto table = dynamic_cast<CaseTable*>(icf_ref.get());
524 if (table)
525 log() << "Table <" << table->name() << "> own "
526 << table->nbElement() << " element(s)";
527 }
528}
529
530/*---------------------------------------------------------------------------*/
531/*---------------------------------------------------------------------------*/
532
533CaseMng::ErrorInfo CaseMng::
534_checkValidFunction(const XmlNode& func_elem,CaseFunctionBuildInfo& cfbi)
535{
536 CaseNodeNames* cnn = caseDocument()->caseNodeNames();
537
538 String func_name = func_elem.attrValue(cnn->name_attribute);
539 if (func_name.null())
540 return ErrorInfo(String::format("missing attribute '{0}'",cnn->name_attribute));
541
542 cfbi.m_name = func_name;
543 if (findFunction(func_name))
544 return ErrorInfo(String::format("function '{0}' is defined several times",func_name));
545
546 String param_name = func_elem.attrValue(cnn->function_parameter);
547 if (param_name.null())
548 return ErrorInfo(String::format("missing attribute '{0}'",cnn->function_parameter));
549
550 String value_name = func_elem.attrValue(cnn->function_value);
551 if (value_name.null())
552 return ErrorInfo(String::format("missing attribute '{0}'",cnn->function_value));
553
554 String comul_name = func_elem.attrValue("comul");
555 String transform_x_name = func_elem.attrValue("comul-x");
556
557 cfbi.m_transform_param_func = transform_x_name;
558 cfbi.m_transform_value_func = comul_name;
559
560 String ustr_time(cnn->time_type);
561 String ustr_iteration(cnn->iteration_type);
562
563 String ustr_real(cnn->real_type);
564 String ustr_real3(cnn->real3_type);
565 String ustr_bool(cnn->bool_type);
566 String ustr_integer(cnn->integer_type);
567 String ustr_string(cnn->string_type);
568
569 UniqueArray<String> valid_param_strs = { ustr_time, ustr_real, ustr_iteration, ustr_integer };
570
571 // Vérifie que le type de paramètre spécifié est correct (réel ou entier)
573 if (param_name==ustr_time || param_name==ustr_real)
574 param_type = ICaseFunction::ParamReal;
575 else if (param_name==ustr_iteration || param_name==ustr_integer)
576 param_type = ICaseFunction::ParamInteger;
577 if (param_type==ICaseFunction::ParamUnknown){
578 return ErrorInfo(String::format("invalid value '{0}' for attribute '{1}'. Valid values are '{2}'.",
579 param_name,cnn->function_parameter,String::join(", ",valid_param_strs)));
580 }
581 cfbi.m_param_type = param_type;
582
583 UniqueArray<String> valid_value_strs = { ustr_real, ustr_real3, ustr_integer, ustr_bool, ustr_string };
584
585 // Vérifie que le type de valeur spécifié est correct (réel ou entier)
587 if (value_name==ustr_real)
588 value_type = ICaseFunction::ValueReal;
589 if (value_name==ustr_integer)
590 value_type = ICaseFunction::ValueInteger;
591 if (value_name==ustr_bool)
592 value_type = ICaseFunction::ValueBool;
593 if (value_name==ustr_string)
594 value_type = ICaseFunction::ValueString;
595 if (value_name==ustr_real3)
596 value_type = ICaseFunction::ValueReal3;
597 if (value_type==ICaseFunction::ValueUnknown)
598 return ErrorInfo(String::format("invalid value '{0}' for attribute '{1}'. Valid values are '{2}'.",
599 value_name,cnn->function_value,String::join(", ",valid_value_strs)));
600 cfbi.m_value_type = value_type;
601
602 // Regarde s'il y a un élément 'deltat-coef' et si oui récupère sa valeur.
603 String deltat_coef_str = func_elem.attrValue(cnn->function_deltat_coef);
604 Real deltat_coef = 0.0;
605 if (!deltat_coef_str.null()){
606 if (builtInGetValue(deltat_coef,deltat_coef_str))
607 return ErrorInfo(String::format("Invalid value '{0}' for attribute '{1}. Can not convert to 'Real' type",
608 deltat_coef_str,cnn->function_deltat_coef));
609 cfbi.m_deltat_coef = deltat_coef;
610 info() << "Coefficient deltat for the function '" << func_name << "' = " << cfbi.m_deltat_coef;
611 }
612
613 return ErrorInfo();
614}
615
616/*---------------------------------------------------------------------------*/
617/*---------------------------------------------------------------------------*/
618
619CaseMng::ErrorInfo CaseMng::
620_readOneTable(const XmlNode& func_elem)
621{
622 CaseFunctionBuildInfo cfbi(traceMng());
623
624 ErrorInfo err_info = _checkValidFunction(func_elem,cfbi);
625 if (err_info.hasError())
626 return err_info;
627
628 CaseNodeNames* cnn = caseDocument()->caseNodeNames();
629
630 String ustr_constant(cnn->function_constant);
631 String ustr_linear(cnn->function_linear);
632 String ustr_value(cnn->function_value);
633
634 String interpolation_name = func_elem.attrValue(cnn->function_interpolation);
635 if (interpolation_name.null())
636 return ErrorInfo(String::format("missing attribute '{0}'",cnn->function_interpolation));
637
638 // Vérifie que le type de la courbe spécifié est correct
640 if (interpolation_name==ustr_constant)
641 interpolation_type = CaseTable::CurveConstant;
642 else if (interpolation_name==ustr_linear)
643 interpolation_type = CaseTable::CurveLinear;
644 if (interpolation_type==CaseTable::CurveUnknown){
645 return ErrorInfo(String::format("Invalid value for attribute '{0}'. Valid values are '{1}' or '{2}'",
646 cnn->function_interpolation,ustr_constant,ustr_linear));
647 }
648
649 // Récupère la liste des valeurs de la fonction
650 XmlNodeList func_value_list = func_elem.children(ustr_value);
651 Integer nb_func_value = func_value_list.size();
652 if (nb_func_value==0)
653 return ErrorInfo("The table has no values");
654
655 auto func = new CaseTable(cfbi,interpolation_type);
657
658 Integer value_index = 0;
659
660 String ustr_x("x");
661 String ustr_y("y");
662 for( const auto& i : func_value_list ) {
663 String param_str = i.child(ustr_x).value();
664 String value_str = i.child(ustr_y).value();
665 param_str = String::collapseWhiteSpace(param_str);
666 value_str = String::collapseWhiteSpace(value_str);
667 if (param_str.null())
668 return ErrorInfo(String::format("index={0} element <x> is missing",value_index));
669 if (value_str.null())
670 return ErrorInfo(String::format("index={0} element <y> is missing",value_index));
671
672 CaseTable::eError error_number = func->appendElement(param_str,value_str);
673 // TODO: AJOUTER DOC DANS LE JDD sur ces informations.
674 if (error_number!=CaseTable::ErrNo){
675 String message = "No info";
676 switch(error_number){
678 message = String::format("parameter '{0}' can not be converted to the 'param' type of the table",param_str);
679 break;
681 message = String::format("value '{0}' can not be converted to the 'value' type of the table",value_str);
682 break;
684 message = "<x> lesser than previous <x>";
685 break;
687 message = "<x> greater than next <x>";
688 break;
690 message = "bad interval";
691 break;
692 case CaseTable::ErrNo:
693 // Ne devrait jamais arriver
694 ARCANE_FATAL("Internal Error");
695 }
696 return ErrorInfo(String::format("index={0} : {1}",value_index,message));
697 }
698 ++value_index;
699 }
700 return ErrorInfo();
701}
702
703/*---------------------------------------------------------------------------*/
704/*---------------------------------------------------------------------------*/
705
706void CaseMng::
707_readOneDotNetFunction(const String& assembly_name,const String& class_name)
708{
709 // Si ce n'est pas encore fait, charge le service '.Net' qui enregistrera
710 // les fonctions
711 if (!m_dotnet_provider.get()){
712 ServiceBuilder<ICaseFunctionDotNetProvider> sb(subDomain());
713 m_dotnet_provider = sb.createReference("ArcaneDefaultDotNetCaseFunctionProvider",SB_AllowNull);
714 if (!m_dotnet_provider.get())
715 ARCANE_FATAL("Can not create '.Net' case function provider. Check that the '.Net' runtime is loaded.");
716 }
717
718 m_dotnet_provider->registerCaseFunctions(this,assembly_name,class_name);
719}
720
721/*---------------------------------------------------------------------------*/
722/*---------------------------------------------------------------------------*/
728{
729 ICaseDocument* doc = _noNullCaseDocument();
730 ICaseDocumentFragment* doc_fragment = doc->fragment();
731 // Cherche les éléments du jeu de données qui ne correspondent pas
732 // à une option connue.
733 XmlNodeList invalid_elems;
735 co->addInvalidChildren(invalid_elems);
736
737 // Cherche les éléments racines qui ne correspondent pas à une option
738
739 // Temporairement pour des raisons de compatibilité, autorise les
740 // éléments à la racine qui ne sont pas utilisés.
741 if (!platform::getEnvironmentVariable("ARCANE_ALLOW_UNKNOWN_ROOT_ELEMENT").null())
742 m_allow_unknown_root_element = true;
743
744 String arcane_element_name = doc->arcaneElement().name();
745 String function_element_name = doc->functionsElement().name();
746 XmlNodeList mesh_elements = doc->meshElements();
747 String mesh_element_name;
748 if (mesh_elements.size()>0)
749 mesh_element_name = mesh_elements[0].name();
750 for( XmlNode node : doc_fragment->rootElement() ){
751 if (node.type()!=XmlNode::ELEMENT)
752 continue;
753 String name = node.name();
754 if (name=="comment")
755 continue;
756 if (name==arcane_element_name || name==function_element_name)
757 continue;
758 if (!mesh_element_name.null() && name==mesh_element_name)
759 continue;
760 bool is_found = false;
762 if (co->rootTagName()==name){
763 is_found = true;
764 break;
765 }
766 }
767 if (!is_found){
768 if (m_allow_unknown_root_element)
769 pwarning() << "-- Unknown root option '" << node.xpathFullName() << "'";
770 else
771 invalid_elems.add(node);
772 }
773 }
774
775 if (!doc_fragment->hasError()){
776 if (!invalid_elems.empty()){
777 for( XmlNode xnode : invalid_elems ){
778 perror() << "-- Unknown root option '" << xnode.xpathFullName() << "'";
779 }
780 pfatal() << "Unknown root option(s) in the input data. "
781 << "You can put these options inside <comment> tags to remove this error";
782 }
783 }
784}
785
786/*---------------------------------------------------------------------------*/
787/*---------------------------------------------------------------------------*/
788
789void CaseMng::
790_readOptions(bool is_phase1)
791{
792 auto read_phase = (is_phase1) ? eCaseOptionReadPhase::Phase1 : eCaseOptionReadPhase::Phase2;
793 for( ICaseOptions* co : CaseOptionsFilterUsed(m_case_options_list)){
794 co->read(read_phase);
795 }
796
797 if (is_phase1){
799 }
800
801 if (!is_phase1){
802 // Recherche les options utilisant des fonctions.
803 m_options_with_function.clear();
804 UniqueArray<CaseOptionBase*> col;
805 for( ICaseOptions* co : CaseOptionsFilterUsed(m_case_options_list)){
806 co->deepGetChildren(col);
807 }
808 for( CaseOptionBase* co : col ){
809 if (co->function()){
810 m_options_with_function.add(co);
811 }
812 }
813 }
814}
815
816/*---------------------------------------------------------------------------*/
817/*---------------------------------------------------------------------------*/
818
821{
822 String lang = _noNullCaseDocument()->fragment()->language();
823
824 auto v = createPrintCaseDocumentVisitor(traceMng(),lang);
825 info() << "-----------------------------------------------------";
826 info();
827 info() << "Input data values:";
828 // Par défaut, utilise le mécanisme historique d'affichage pour que les
829 // utilisateurs n'aient pas trop de différences d'affichage avec les
830 // nouvelles versions de Arcane.
831 // TODO: vérifier que le nouvel affichage est identique à l'ancien pour
832 // la plupart des options.
833 const bool use_old = true;
835 if (use_old)
836 co->printChildren(lang,0);
837 else
838 co->visit(v.get());
839 }
840
841 info() << "-----------------------------------------------------";
842}
843
844/*---------------------------------------------------------------------------*/
845/*---------------------------------------------------------------------------*/
846
848updateOptions(Real current_time,Real current_deltat,Integer current_iteration)
849{
850 Trace::Setter mci(traceMng(),msgClassName());
851
852 for( CaseOptionBase* co : m_options_with_function ){
853 ICaseFunction* cf = co->function();
854 Real deltat_coef = cf->deltatCoef();
855 Real t = current_time;
856 if (!math::isZero(deltat_coef)){
857 Real to_add = deltat_coef * current_deltat;
858 t += to_add;
859 }
860 co->updateFromFunction(t,current_iteration);
861 }
862}
863
864/*---------------------------------------------------------------------------*/
865/*---------------------------------------------------------------------------*/
866
867Ref<ICaseFunction> CaseMng::
868findFunctionRef(const String& name) const
869{
870 for( auto& func_ref : m_functions )
871 if (func_ref->name()==name)
872 return func_ref;
873 return {};
874}
875
876/*---------------------------------------------------------------------------*/
877/*---------------------------------------------------------------------------*/
878
880findFunction(const String& name) const
881{
882 return findFunctionRef(name).get();
883}
884
885/*---------------------------------------------------------------------------*/
886/*---------------------------------------------------------------------------*/
887
890{
891 _removeFunction(func,false);
892}
893
894/*---------------------------------------------------------------------------*/
895/*---------------------------------------------------------------------------*/
896
898removeFunction(ICaseFunction* func,bool do_free)
899{
900 _removeFunction(func,do_free);
901}
902
903/*---------------------------------------------------------------------------*/
904/*---------------------------------------------------------------------------*/
905
906void CaseMng::
907_removeFunction(ICaseFunction* func,bool do_delete)
908{
909 // Plus utilisé depuis qu'on utilise un compte de référence.
910 ARCANE_UNUSED(do_delete);
911 Integer index = 0;
912 bool is_found = false;
913 for( auto& f : m_functions ){
914 if (f.get()==func){
915 is_found = true;
916 break;
917 }
918 ++index;
919 }
920 if (is_found){
921 m_functions.removeAt(index);
922 }
923}
924
925/*---------------------------------------------------------------------------*/
926/*---------------------------------------------------------------------------*/
927
930{
931 m_functions.add(func);
932}
933
934/*---------------------------------------------------------------------------*/
935/*---------------------------------------------------------------------------*/
936
938readCaseDocument(const String& filename,ByteConstArrayView case_bytes)
939{
941 {
942 // Pour l'instant lit dans la section critique car cela provoque
943 // certains plantages sinon de temps en temps (à étudier)
944 CriticalSection cs(sm->threadMng());
945 _readCaseDocument(filename,case_bytes);
946 }
947 return m_case_document.get();
948}
949
950/*---------------------------------------------------------------------------*/
951/*---------------------------------------------------------------------------*/
952
953void CaseMng::
954_readCaseDocument(const String& filename,ByteConstArrayView case_bytes)
955{
956 if (m_case_document.get())
957 // Déjà lu...
958 return;
959
961 IIOMng* io_mng = m_sub_domain->parallelMng()->ioMng();
962 String printed_filename = filename;
963
964 IXmlDocumentHolder* case_doc = io_mng->parseXmlBuffer(case_bytes,filename);
965 if (!case_doc){
966 info() << "XML Memory File:";
967 info() << filename;
968 pfatal() << "Failed to analyze the input data " << printed_filename;
969 }
970
971 m_case_document = app->mainFactory()->createCaseDocument(app,case_doc);
972
973 CaseNodeNames* cnn = caseDocument()->caseNodeNames();
974
975 String code_name = app->applicationInfo().codeName();
976 XmlNode root_elem = m_case_document->fragment()->rootElement();
977 if (root_elem.name()!=cnn->root){
978 pfatal() << "The root element <" << root_elem.name() << "> has to be <" << cnn->root << ">";
979 }
980
981 if (root_elem.attrValue(cnn->code_name)!=code_name){
982 pfatal() << "The file is not a case of code '" << code_name << "'";
983 }
984
985 String case_codeversion = root_elem.attrValue(cnn->code_version);
986 String code_version(app->majorAndMinorVersionStr());
987 String code_version2(app->mainVersionStr());
988 if (case_codeversion!=code_version && case_codeversion!=code_version2){
989 if (!m_sub_domain->session()->checkIsValidCaseVersion(case_codeversion))
990 pfatal() << "The version number of the file (" << case_codeversion
991 << ") doesn't match the version of the code '"
992 << code_name << "' (" << code_version << ").";
993 }
994}
995
996/*---------------------------------------------------------------------------*/
997/*---------------------------------------------------------------------------*/
998
1000internalReadOneOption(ICaseOptions* opt,bool is_phase1)
1001{
1003 ICaseDocumentFragment* doc = opt->caseDocumentFragment();
1005 if (is_phase1)
1007 OptionsReader reader(this);
1008 reader.addOption(opt);
1009 reader.read(is_phase1);
1010 XmlNodeList invalid_elems;
1011 opt->addInvalidChildren(invalid_elems);
1012 _printErrors(doc,is_phase1);
1013}
1014
1015/*---------------------------------------------------------------------------*/
1016/*---------------------------------------------------------------------------*/
1017
1018} // End namespace Arcane
1019
1020/*---------------------------------------------------------------------------*/
1021/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Integer size() const
Nombre d'éléments du vecteur.
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
const String & codeName() const
Retourne le nom du code de calcul lié l'application.
Tableau d'items de types quelconques.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Classe gérant la traduction d'un jeu de données dans une autre langue.
Informations pour construire une instance de CaseFunction.
Gestionnaire d'un cas.
Definition CaseMng.cc:80
void internalReadOneOption(ICaseOptions *opt, bool is_phase1) override
Implémentation via ICaseMngInternal.
Definition CaseMng.cc:1000
void setAllowUnkownRootElelement(bool v) override
Positionne l'autorisation des éléments inconnus à la racine du document.
Definition CaseMng.cc:185
void readOptions(bool is_phase1) override
Lit les options du jeu de donnée correspondant aux modules utilisés.
Definition CaseMng.cc:328
CaseFunctionList m_functions
Liste des fonctions.
Definition CaseMng.cc:217
bool m_is_function_read
Indique si les fonctions ont déjà été lues.
Definition CaseMng.cc:224
IObservable * observable(eCaseMngEventType type) override
Observable sur l'instance.
Definition CaseMng.cc:188
IApplication * application() override
Application associée.
Definition CaseMng.cc:151
void printOptions() override
Affiche les valeurs des options.
Definition CaseMng.cc:820
ISubDomain * subDomain() override
Gestionnaire de sous-domaine.
Definition CaseMng.cc:150
bool isTreatWarningAsError() const override
Indique si les avertissements dans le jeu de données doivent être traités comme des erreurs et provoq...
Definition CaseMng.cc:183
bool isAllowUnkownRootElelement() const override
Indique si les éléments inconnus à la racine du document sont autorisés.
Definition CaseMng.cc:186
ISubDomain * m_sub_domain
Gestionnaire de sous-domain.
Definition CaseMng.cc:215
void registerOptions(ICaseOptions *) override
Enregistre une liste d'options du jeu de donnée.
Definition CaseMng.cc:447
ICaseFunction * findFunction(const String &name) const override
Retourne la fonction de nom name ou nullptr s'il n'y en a pas.
Definition CaseMng.cc:880
const ParameterListWithCaseOption & parameters() const
Liste des paramètres pouvant surcharger le jeu de données.
Definition CaseMng.cc:206
ITraceMng * traceMng() override
Gestionnaire de traces.
Definition CaseMng.cc:148
void unregisterOptions(ICaseOptions *) override
Déseregistre une liste d'options du jeu de donnée.
Definition CaseMng.cc:459
void removeFunction(ICaseFunction *func, bool dofree) override
Supprime une fonction.
Definition CaseMng.cc:898
ICaseDocumentFragment * createDocumentFragment(IXmlDocumentHolder *document) override
Crée un fragment.
Definition CaseMng.cc:202
CaseOptionsList m_case_options_list
Liste des options du cas.
Definition CaseMng.cc:218
void setTreatWarningAsError(bool v) override
Positionne la manière de traiter les avertissements.
Definition CaseMng.cc:182
CaseOptionsCollection blocks() const override
Collection des blocs d'options.
Definition CaseMng.cc:180
void updateOptions(Real current_time, Real current_deltat, Integer current_iteration) override
Met à jour les options basée sur une table de marche en temps.
Definition CaseMng.cc:848
IMeshMng * meshMng() const override
Gestionnaire de maillage associé
Definition CaseMng.cc:149
CaseFunctionCollection functions() override
Retourne la liste des tables.
Definition CaseMng.cc:170
IPhysicalUnitSystem * physicalUnitSystem() const override
Système d'unité associé.
Definition CaseMng.cc:152
ICaseDocument * readCaseDocument(const String &filename, ByteConstArrayView bytes) override
Lit le document XML du jeu de données.
Definition CaseMng.cc:938
ICaseDocument * caseDocument() override
Document XML du jeu de données (peut être nul si pas de jeu de donneés)
Definition CaseMng.cc:153
ICaseMngInternal * _internalImpl() override
Implémentation interne.
Definition CaseMng.cc:197
void _searchInvalidOptions()
Recherche les options invalides du jeu de données.
Definition CaseMng.cc:727
void readFunctions() override
Lit les tables du jeu de donnée.
Definition CaseMng.cc:415
ICaseDocumentFragment * caseDocumentFragment() override
Fragment du Document XML associé au jeu de données (peut être nul si pas de jeu de donneés)
Definition CaseMng.cc:154
void addFunction(ICaseFunction *func) override
Ajoute la fonction func.
Definition CaseMng.cc:174
Noms des noeuds XML d'un jeu de données Arcane.
Classe de base d'une option du jeu de donnée.
eCurveType
Type de la courbe de la table.
Definition CaseTable.h:64
@ CurveUnknown
Type de courbe inconnu.
Definition CaseTable.h:65
@ CurveLinear
Courbe linéaire par morceau.
Definition CaseTable.h:67
@ CurveConstant
Courbe constante par morceau.
Definition CaseTable.h:66
eError
Type des erreurs retournées par la classe.
Definition CaseTable.h:47
@ ErrCanNotConvertParamToRightType
Indique que la conversion du paramètre vers le type souhaité est impossible.
Definition CaseTable.h:52
@ ErrBadRange
Indique qu'un indice d'un élément n'est pas valide.
Definition CaseTable.h:50
@ ErrNotGreaterThanPrevious
Indique que le paramètre n'est pas supérieur au précédent.
Definition CaseTable.h:56
@ ErrNotLesserThanNext
Indique que le paramètre n'est pas inférieur au suivant.
Definition CaseTable.h:58
@ ErrCanNotConvertValueToRightType
Indique que la conversion de la valeur vers le type souhaité est impossible.
Definition CaseTable.h:54
Section critique en multi-thread.
Interface de l'application.
virtual IMainFactory * mainFactory() const =0
Manufacture principale.
virtual String mainVersionStr() const =0
Numéro de version principal (sans la béta) de l'application.
virtual String majorAndMinorVersionStr() const =0
Numéro de version majeur et mineure sous la forme M.m.
virtual IParallelSuperMng * parallelSuperMng()=0
Gestionnaire superviseur du parallélisme.
virtual const ApplicationInfo & applicationInfo() const =0
Informations sur l'exécutable.
Interface d'une partie d'un jeu de données.
virtual CaseNodeNames * caseNodeNames()=0
Retourne l'instance contenant les noms des noeuds XML par langage.
virtual XmlNode rootElement()=0
Retourne l'élément racine.
virtual String language() const =0
Langage utilisé dans le jeu de données.
virtual void clearErrorsAndWarnings()=0
Supprime les messages d'erreurs et d'avertissements enregistrés.
Interface d'une classe gérant un document XML du jeu de données.
virtual XmlNode functionsElement()=0
Retourne l'élément racine des fonctions.
virtual const XmlNodeList & meshElements()=0
Retourne l'élément racine des informations de maillage.
virtual XmlNode arcaneElement()=0
Retourne l'élément des informations pour Arcane.
virtual ICaseDocumentFragment * fragment()=0
Fragment correspondant à ce document.
virtual CaseNodeNames * caseNodeNames()=0
Retourne l'instance contenant les noms des noeuds XML par langage.
Interface d'une fonction du jeu de données.
virtual Real deltatCoef() const =0
Valeur du coefficient multiplicateur du deltat.
eParamType
Type d'un paramètre d'une fonction.
@ ParamUnknown
Type de paramètre inconnu.
@ ParamReal
Paramètre de type Real.
@ ParamInteger
Paramètre de type Integer.
eValueType
Type d'une valeur d'une fonction.
@ ValueReal3
Valeur de type 'Real3'.
@ ValueUnknown
Type de la valeur inconnu.
@ ValueInteger
Valeur de type entière.
@ ValueString
Valeur de type chaîne de caractères.
@ ValueReal
Valeur de type réelle.
@ ValueBool
Valeur de type entière.
Partie interne de ICaseMng.
Interface du gestionnaire de cas.
Definition ICaseMng.h:56
Interface d'une liste d'options du jeu de données.
virtual IModule * caseModule() const =0
Retourne le module associé ou nullptr s'il n'y en a pas.
virtual String rootTagName() const =0
Nom de l'élément dans le langage du jeu de données.
Interface du gestionnaire des entrées sorties.
Definition IIOMng.h:36
virtual IXmlDocumentHolder * parseXmlBuffer(Span< const Byte > buffer, const String &name)=0
Lit et analyse le fichier XML contenu dans le buffer buffer.
virtual ICaseDocument * createCaseDocument(IApplication *)=0
Crée une instance d'un document du jeu de données.
Interface du gestionnaire des maillages.
Definition IMeshMng.h:40
Interface d'un module.
Definition IModule.h:39
virtual bool used() const =0
true si le module est utilisé.
virtual IIOMng * ioMng() const =0
Gestionnaire des entrées/sorties.
Classe abstraite du superviseur de parallélisme.
virtual IThreadMng * threadMng() const =0
Gestionnaire de thread.
Interface d'un système d'unité.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual IApplication * application()=0
Application.
virtual IParallelMng * parallelMng()=0
Retourne le gestionnaire de parallélisme.
Interface du gestionnaire de traces.
Gestionnaire d'un document DOM.
Implémentation d'une collection d'éléments sous forme de vecteur.
Liste d'observables.
Liste de paramètres avec informations pour surcharger les options du jeu de données.
T * get() const
Retourne l'objet référé par l'instance.
Definition Ptr.h:121
Référence à une instance.
static ThatClass create(InstanceType *t)
Créé une référence à partir de l'instance t.
Implémentation thread-safe d'un compteur de référence.
Encapsulation d'un pointeur qui se détruit automatiquement.
Definition ScopedPtr.h:44
Informations pour créer un service.
Classe utilitaire pour retrouver un ou plusieurs services implémentant l'interface InterfaceType.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:305
void writeBytes(std::ostream &o) const
Écrit la chaîne au format UTF-8 sur le flot o.
Definition String.cc:1237
static String collapseWhiteSpace(const String &rhs)
Effectue une normalisation des caractères espaces.
Definition String.cc:453
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage pfatal() const
Flot pour un message d'erreur fatale en parallèle.
TraceMessage log() const
Flot pour un message de log.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessage warning() const
Flot pour un message d'avertissement.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage perror() const
TraceMessage pwarning() const
Positionne une classe de message.
Vecteur 1D de données avec sémantique par valeur (style STL).
Liste de noeuds d'un arbre DOM.
Definition XmlNodeList.h:35
Noeud d'un arbre DOM.
Definition XmlNode.h:51
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
@ ELEMENT
The node is an Element.
Definition XmlNode.h:87
String name() const
Nom du noeud.
Definition XmlNode.cc:132
bool isZero(const BuiltInProxy< _Type > &a)
Teste si une valeur est exactement égale à zéro.
ARCCORE_BASE_EXPORT String getEnvironmentVariable(const String &name)
Variable d'environnement du nom name.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ SB_AllowNull
Autorise l'absence du service.
eCaseOptionReadPhase
Phases de la lecture.
eCaseMngEventType
Types des évènements supportés par ICaseMng.
Definition ICaseMng.h:39
@ BeginReadOptionsPhase2
Évènement généré avant de lire les options dans la phase 2.
Definition ICaseMng.h:43
@ BeginReadOptionsPhase1
Évènement généré avant de lire les options dans la phase 1.
Definition ICaseMng.h:41
Int32 Integer
Type représentant un entier.
List< ICaseOptions * > CaseOptionsList
Tableau d'options du jeu de données.
Collection< ICaseOptions * > CaseOptionsCollection
Collection d'options du jeu de données.
double Real
Type représentant un réel.
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:480
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.