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