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"
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"
53#include "arcane/impl/CaseDocumentLangTranslator.h"
64extern "C++" std::unique_ptr<ICaseDocumentVisitor>
91 void read(
bool is_phase1);
97 void _read(
bool is_phase1);
107 explicit ErrorInfo(
const String& error_message)
109 , m_error_message(error_message)
117 bool hasError()
const {
return m_has_error; }
118 const String& errorMessage()
const {
return m_error_message; }
129 class CaseOptionsFilterUsed
134 : m_begin(opt_list.begin())
135 , m_end(opt_list.end())
140 auto begin()
const {
return m_begin; }
141 auto end()
const {
return m_end; }
144 bool do_continue =
true;
147 if (m_begin >= m_end)
151 do_continue = (md && !md->
used());
152 }
while (do_continue);
157 CaseOptionsList::const_iterator m_begin;
158 CaseOptionsList::const_iterator m_end;
210 return m_observables[type];
224 return arcaneCreateCaseDocumentFragment(
traceMng(), document);
231 String msgClassName()
const {
return "CaseMng"; }
240 bool m_treat_warning_as_error =
false;
241 bool m_allow_unknown_root_element =
true;
252 void _readOptions(
bool is_phase1);
253 void _readFunctions();
256 void _checkTranslateDocument();
265 void _readOneDotNetFunction(
const String& assembly_name,
const String& class_name);
271void CaseMng::OptionsReader::
282void CaseMng::OptionsReader::
286 for (ICaseOptions* co : m_options) {
287 co->read(read_phase);
294void CaseMng::OptionsReader::
295_searchInvalidOptions()
298 XmlNodeList invalid_elems;
299 for (ICaseOptions* co : m_options)
300 co->addInvalidChildren(invalid_elems);
307CaseMng(ISubDomain* sub_domain)
310, m_treat_warning_as_error(false)
313 m_treat_warning_as_error =
true;
320 m_parameters.addParameters(sub_domain->application()->applicationInfo().commandLineArguments().parameters());
353 info() <<
"Reading the input data (phase1): language '"
357 info() <<
"Reading the input data (phase2)";
372 _readOptions(is_phase1);
373 _printErrors(doc, is_phase1);
375 _checkTranslateDocument();
382_checkTranslateDocument()
387 if (!tr_lang.
null()) {
388 info() <<
"Generating translation for case file to lang=" << tr_lang;
390 String convert_string = translator.translate(
this, tr_lang);
392 std::ofstream ofile(
"convert_info.txt");
408 if (!m_treat_warning_as_error) {
410 if (doc->hasWarnings()) {
412 doc->printWarnings(ostr());
413 pwarning() <<
"The input data are not coherent:\n\n"
418 bool has_error = doc->hasError();
419 if (doc->hasWarnings() && m_treat_warning_as_error && !is_phase1)
424 if (m_treat_warning_as_error && doc->hasWarnings())
425 doc->printWarnings(ostr());
426 doc->printErrors(ostr());
427 ARCANE_FATAL(
"Input data are invalid:\n\n{0}", ostr.str());
448 info() <<
"NB_CASE_FUNCTION_PROVIDER_FACTORY = " << factories.
size();
449 for (
const auto& factory : factories) {
452 info() <<
"FOUND CASE FUNCTION PROVIDER (V2)!";
453 cfp->registerCaseFunctions(
this);
490 bool has_error =
false;
500 XmlNode funcs_elem = case_root_elem.
child(cnn->functions);
503 String ustr_table(cnn->function_table);
504 String ustr_script(cnn->function_script);
506 if (functions_elem.
empty())
509 for (
XmlNode node : functions_elem) {
513 if (node.isNamed(ustr_table)) {
514 ErrorInfo err_info = _readOneTable(node);
515 if (err_info.hasError()) {
517 String table_name = node.attrValue(cnn->name_attribute);
518 if (table_name.
null())
519 error() <<
" Error in element '" << node.xpathFullName() <<
"' : "
520 << err_info.errorMessage();
522 error() <<
" Error in table named '" << table_name <<
"' : "
523 << err_info.errorMessage();
526 else if (node.isNamed(
"external-assembly")) {
527 String assembly_name = node.expectedChild(
"assembly-name").value();
528 String class_name = node.expectedChild(
"class-name").value();
529 _readOneDotNetFunction(assembly_name, class_name);
532 warning() <<
"Unknown node in functions: " << node.xpathFullName();
543 auto table =
dynamic_cast<CaseTable*
>(icf_ref.get());
545 log() <<
"Table <" << table->name() <<
"> own "
546 << table->nbElement() <<
" element(s)";
558 String func_name = func_elem.attrValue(cnn->name_attribute);
559 if (func_name.null())
560 return ErrorInfo(String::format(
"missing attribute '{0}'", cnn->name_attribute));
562 cfbi.m_name = func_name;
564 return ErrorInfo(String::format(
"function '{0}' is defined several times", func_name));
566 String param_name = func_elem.attrValue(cnn->function_parameter);
567 if (param_name.null())
568 return ErrorInfo(String::format(
"missing attribute '{0}'", cnn->function_parameter));
570 String value_name = func_elem.attrValue(cnn->function_value);
571 if (value_name.null())
572 return ErrorInfo(String::format(
"missing attribute '{0}'", cnn->function_value));
574 String comul_name = func_elem.attrValue(
"comul");
575 String transform_x_name = func_elem.attrValue(
"comul-x");
577 cfbi.m_transform_param_func = transform_x_name;
578 cfbi.m_transform_value_func = comul_name;
580 String ustr_time(cnn->time_type);
581 String ustr_iteration(cnn->iteration_type);
583 String ustr_real(cnn->real_type);
584 String ustr_real3(cnn->real3_type);
585 String ustr_bool(cnn->bool_type);
586 String ustr_integer(cnn->integer_type);
587 String ustr_string(cnn->string_type);
589 UniqueArray<String> valid_param_strs = { ustr_time, ustr_real, ustr_iteration, ustr_integer };
593 if (param_name == ustr_time || param_name == ustr_real)
595 else if (param_name == ustr_iteration || param_name == ustr_integer)
598 return ErrorInfo(String::format(
"invalid value '{0}' for attribute '{1}'. Valid values are '{2}'.",
599 param_name, cnn->function_parameter, String::join(
", ", valid_param_strs)));
601 cfbi.m_param_type = param_type;
603 UniqueArray<String> valid_value_strs = { ustr_real, ustr_real3, ustr_integer, ustr_bool, ustr_string };
607 if (value_name == ustr_real)
609 if (value_name == ustr_integer)
611 if (value_name == ustr_bool)
613 if (value_name == ustr_string)
615 if (value_name == ustr_real3)
618 return ErrorInfo(String::format(
"invalid value '{0}' for attribute '{1}'. Valid values are '{2}'.",
619 value_name, cnn->function_value, String::join(
", ", valid_value_strs)));
620 cfbi.m_value_type = value_type;
623 String deltat_coef_str = func_elem.attrValue(cnn->function_deltat_coef);
624 Real deltat_coef = 0.0;
625 if (!deltat_coef_str.null()) {
626 if (builtInGetValue(deltat_coef, deltat_coef_str))
627 return ErrorInfo(String::format(
"Invalid value '{0}' for attribute '{1}. Can not convert to 'Real' type",
628 deltat_coef_str, cnn->function_deltat_coef));
629 cfbi.m_deltat_coef = deltat_coef;
630 info() <<
"Coefficient deltat for the function '" << func_name <<
"' = " << cfbi.m_deltat_coef;
640_readOneTable(
const XmlNode& func_elem)
642 CaseFunctionBuildInfo cfbi(
traceMng());
644 ErrorInfo err_info = _checkValidFunction(func_elem, cfbi);
645 if (err_info.hasError())
650 String ustr_constant(cnn->function_constant);
651 String ustr_linear(cnn->function_linear);
652 String ustr_value(cnn->function_value);
654 String interpolation_name = func_elem.attrValue(cnn->function_interpolation);
655 if (interpolation_name.null())
656 return ErrorInfo(String::format(
"missing attribute '{0}'", cnn->function_interpolation));
660 if (interpolation_name == ustr_constant)
662 else if (interpolation_name == ustr_linear)
665 return ErrorInfo(String::format(
"Invalid value for attribute '{0}'. Valid values are '{1}' or '{2}'",
666 cnn->function_interpolation, ustr_constant, ustr_linear));
670 XmlNodeList func_value_list = func_elem.children(ustr_value);
671 Integer nb_func_value = func_value_list.size();
672 if (nb_func_value == 0)
673 return ErrorInfo(
"The table has no values");
675 auto func =
new CaseTable(cfbi, interpolation_type);
682 for (
const auto& i : func_value_list) {
683 String param_str = i.child(ustr_x).value();
684 String value_str = i.child(ustr_y).value();
687 if (param_str.null())
688 return ErrorInfo(String::format(
"index={0} element <x> is missing", value_index));
689 if (value_str.null())
690 return ErrorInfo(String::format(
"index={0} element <y> is missing", value_index));
694 if (error_number != CaseTable::ErrNo) {
695 String message =
"No info";
696 switch (error_number) {
698 message = String::format(
"parameter '{0}' can not be converted to the 'param' type of the table", param_str);
701 message = String::format(
"value '{0}' can not be converted to the 'value' type of the table", value_str);
704 message =
"<x> lesser than previous <x>";
707 message =
"<x> greater than next <x>";
710 message =
"bad interval";
712 case CaseTable::ErrNo:
716 return ErrorInfo(String::format(
"index={0} : {1}", value_index, message));
727_readOneDotNetFunction(
const String& assembly_name,
const String& class_name)
731 if (!m_dotnet_provider.get()) {
732 ServiceBuilder<ICaseFunctionDotNetProvider> sb(
subDomain());
733 m_dotnet_provider = sb.createReference(
"ArcaneDefaultDotNetCaseFunctionProvider",
SB_AllowNull);
734 if (!m_dotnet_provider.get())
735 ARCANE_FATAL(
"Can not create '.Net' case function provider. Check that the '.Net' runtime is loaded.");
738 m_dotnet_provider->registerCaseFunctions(
this, assembly_name, class_name);
755 co->addInvalidChildren(invalid_elems);
761 m_allow_unknown_root_element =
true;
767 if (mesh_elements.size() > 0)
768 mesh_element_name = mesh_elements[0].name();
772 String name = node.name();
773 if (name ==
"comment")
775 if (name == arcane_element_name || name == function_element_name)
777 if (!mesh_element_name.
null() && name == mesh_element_name)
779 bool is_found =
false;
781 if (co->rootTagName() == name) {
787 if (m_allow_unknown_root_element)
788 pwarning() <<
"-- Unknown root option '" << node.xpathFullName() <<
"'";
790 invalid_elems.
add(node);
794 if (!doc_fragment->hasError()) {
795 if (!invalid_elems.
empty()) {
796 for (
XmlNode xnode : invalid_elems) {
797 perror() <<
"-- Unknown root option '" << xnode.xpathFullName() <<
"'";
799 pfatal() <<
"Unknown root option(s) in the input data. "
800 <<
"You can put these options inside <comment> tags to remove this error";
809_readOptions(
bool is_phase1)
813 co->read(read_phase);
822 m_options_with_function.clear();
823 UniqueArray<CaseOptionBase*> col;
825 co->deepGetChildren(col);
827 for (CaseOptionBase* co : col) {
828 if (co->function()) {
829 m_options_with_function.add(co);
841 String lang = _noNullCaseDocument()->fragment()->language();
843 auto v = createPrintCaseDocumentVisitor(
traceMng(), lang);
844 info() <<
"-----------------------------------------------------";
846 info() <<
"Input data values:";
850 const bool use_old =
true;
853 co->printChildren(lang, 0);
858 info() <<
"-----------------------------------------------------";
872 Real t = current_time;
874 Real to_add = deltat_coef * current_deltat;
877 co->updateFromFunction(t, current_iteration);
885findFunctionRef(
const String& name)
const
888 if (func_ref->name() == name)
899 return findFunctionRef(name).get();
908 _removeFunction(func,
false);
917 _removeFunction(func, do_free);
927 ARCANE_UNUSED(do_delete);
929 bool is_found =
false;
931 if (f.get() == func) {
962 _readCaseDocument(filename, case_bytes);
964 return m_case_document.get();
973 if (m_case_document.
get())
979 String printed_filename = filename;
983 info() <<
"XML Memory File:";
985 pfatal() <<
"Failed to analyze the input data " << printed_filename;
993 XmlNode root_elem = m_case_document->fragment()->rootElement();
994 if (root_elem.name() != cnn->root) {
995 pfatal() <<
"The root element <" << root_elem.name() <<
"> has to be <" << cnn->root <<
">";
998 if (root_elem.attrValue(cnn->code_name) != code_name) {
999 pfatal() <<
"The file is not a case of code '" << code_name <<
"'";
1002 String case_codeversion = root_elem.attrValue(cnn->code_version);
1005 if (case_codeversion != code_version && case_codeversion != code_version2) {
1006 if (!
m_sub_domain->session()->checkIsValidCaseVersion(case_codeversion))
1007 pfatal() <<
"The version number of the file (" << case_codeversion
1008 <<
") doesn't match the version of the code '"
1009 << code_name <<
"' (" << code_version <<
").";
1025 reader.addOption(opt);
1026 reader.read(is_phase1);
1028 opt->addInvalidChildren(invalid_elems);
1029 _printErrors(doc, is_phase1);
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS()
Macro to define methods managing counters of references.
Integer size() const
Number of elements in the vector.
bool empty() const
Capacity (number of allocated elements) of the vector.
const String & codeName() const
Returns the name of the calculation code linked to the application.
Base class for 1D data vectors.
void add(ConstReferenceType val)
Adds element val to the end of the array.
Class managing the translation of a dataset into another language.
Information to build an instance of CaseFunction.
void internalReadOneOption(ICaseOptions *opt, bool is_phase1) override
Implementation via ICaseMngInternal.
void setAllowUnkownRootElelement(bool v) override
Sets the permission for unknown elements at the document root.
void readOptions(bool is_phase1) override
Reads the dataset options corresponding to the used modules.
CaseFunctionList m_functions
List of functions.
bool m_is_function_read
Indicates if functions have already been read.
IObservable * observable(eCaseMngEventType type) override
Observable on the instance.
IApplication * application() override
Associated application.
void printOptions() override
Prints the option values.
ISubDomain * subDomain() override
Sub-domain manager.
bool isTreatWarningAsError() const override
Indicates whether warnings in the dataset should be treated as errors and cause the code to stop.
bool isAllowUnkownRootElelement() const override
Indicates whether unknown elements at the document root are allowed.
ISubDomain * m_sub_domain
Sub-domain manager.
void registerOptions(ICaseOptions *) override
Registers a list of dataset options.
ICaseFunction * findFunction(const String &name) const override
Returns the function by name name or nullptr if none exists.
const ParameterListWithCaseOption & parameters() const
List of parameters that can override the dataset.
ITraceMng * traceMng() override
Trace manager.
void unregisterOptions(ICaseOptions *) override
Unregisters a list of dataset options.
void removeFunction(ICaseFunction *func, bool dofree) override
Deletes a function.
ICaseDocumentFragment * createDocumentFragment(IXmlDocumentHolder *document) override
Creates a fragment.
CaseOptionsList m_case_options_list
List of case options.
void setTreatWarningAsError(bool v) override
Sets the way warnings are treated.
CaseOptionsCollection blocks() const override
Collection of option blocks.
void updateOptions(Real current_time, Real current_deltat, Integer current_iteration) override
Updates the options based on a time-marching table.
IMeshMng * meshMng() const override
Associated mesh manager.
CaseFunctionCollection functions() override
Returns the list of tables.
IPhysicalUnitSystem * physicalUnitSystem() const override
Associated unit system.
ICaseDocument * readCaseDocument(const String &filename, ByteConstArrayView bytes) override
Reads the XML document of the dataset.
ICaseDocument * caseDocument() override
XML document of the dataset (can be null if no dataset).
ICaseMngInternal * _internalImpl() override
Internal implementation.
void _searchInvalidOptions()
Searches for invalid data set options.
void readFunctions() override
Reads the dataset tables.
ICaseDocumentFragment * caseDocumentFragment() override
Fragment of the XML Document associated with the dataset (can be null if no dataset).
void addFunction(ICaseFunction *func) override
Adds the function func.
XML node names of an Arcane dataset.
Base class for a data set option.
eCurveType
Type of the table curve.
@ CurveUnknown
Unknown curve type.
@ CurveLinear
Piecewise linear curve.
@ CurveConstant
Piecewise constant curve.
eError
Types of errors returned by the class.
@ ErrCanNotConvertParamToRightType
Indicates that converting the parameter to the desired type is impossible.
@ ErrBadRange
Indicates that an element index is not valid.
@ ErrNotGreaterThanPrevious
Indicates that the parameter is not greater than the previous one.
@ ErrNotLesserThanNext
Indicates that the parameter is not less than the next one.
@ ErrCanNotConvertValueToRightType
Indicates that converting the value to the desired type is impossible.
Critical section in multi-thread.
virtual IMainFactory * mainFactory() const =0
Main factory.
virtual String mainVersionStr() const =0
Main application version number (without beta).
virtual String majorAndMinorVersionStr() const =0
Major and minor version number in M.m format.
virtual IParallelSuperMng * parallelSuperMng()=0
Supervisory parallelism manager.
virtual const ApplicationInfo & applicationInfo() const =0
Executable information.
Interface of a part of a dataset.
virtual CaseNodeNames * caseNodeNames()=0
Returns the instance containing the names of XML nodes by language.
virtual XmlNode rootElement()=0
Returns the root element.
virtual String language() const =0
Language used in the dataset.
virtual void clearErrorsAndWarnings()=0
Clears the recorded error and warning messages.
Interface of a class managing an XML document of the dataset.
virtual XmlNode functionsElement()=0
Returns the root element of the functions.
virtual const XmlNodeList & meshElements()=0
Returns the root element of the mesh information.
virtual XmlNode arcaneElement()=0
Returns the information element for Arcane.
virtual ICaseDocumentFragment * fragment()=0
Fragment corresponding to this document.
virtual CaseNodeNames * caseNodeNames()=0
Returns the instance containing the names of XML nodes by language.
Interface of a dataset function.
virtual Real deltatCoef() const =0
Value of the deltat multiplier coefficient.
eParamType
Type of a function parameter.
@ ParamUnknown
Unknown parameter type.
@ ParamReal
Real type parameter.
@ ParamInteger
Integer type parameter.
eValueType
Type of a function value.
@ ValueReal3
'Real3' type value
@ ValueUnknown
Unknown value type.
@ ValueInteger
Integer type value.
@ ValueString
String type value.
@ ValueReal
Real type value.
@ ValueBool
Boolean type value.
Internal part of ICaseMng.
Interface for a list of data set options.
virtual IModule * caseModule() const =0
Returns the associated module or nullptr if none exists.
virtual String rootTagName() const =0
Name of the element in the data set language.
Interface of the input/output manager.
virtual IXmlDocumentHolder * parseXmlBuffer(Span< const Byte > buffer, const String &name)=0
Reads and parses the XML file contained in the buffer buffer.
virtual ICaseDocument * createCaseDocument(IApplication *)=0
Creates an instance of a case document.
virtual bool used() const =0
true if the module is used.
Interface of an observable.
virtual IIOMng * ioMng() const =0
I/O manager.
Abstract class of the parallelism supervisor.
virtual IThreadMng * threadMng() const =0
Thread manager.
Interface of a unit system.
Interface of the subdomain manager.
virtual IApplication * application()=0
Application.
virtual IParallelMng * parallelMng()=0
Returns the parallelism manager.
Manager of a DOM document.
Implementation of a collection of elements in vector form.
Parameter list with information to override dataset options.
T * get() const
Returns the object referenced by the instance.
Reference to an instance.
static ThatClass create(InstanceType *t)
Creates a reference from the instance t.
Thread-safe implementation of a reference counter.
Encapsulation of an automatically destructing pointer.
Information for creating a service.
Utility class to find one or more services implementing the InterfaceType interface.
Unicode character string.
bool null() const
Returns true if the string is null.
void writeBytes(std::ostream &o) const
Writes the string in UTF-8 format to the stream o.
static String collapseWhiteSpace(const String &rhs)
Performs whitespace character normalization.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage pfatal() const
Flow for a parallel fatal error message.
TraceMessage log() const
Flow for a log message.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
TraceMessage warning() const
Flow for a warning message.
ITraceMng * traceMng() const
Trace manager.
TraceMessage perror() const
TraceMessage pwarning() const
1D data vector with value semantics (STL style).
List of nodes of a DOM tree.
XmlNode child(const String &name) const
Child node of this node with name name.
XmlNodeList children(const String &name) const
Set of child nodes of this node having the name name.
@ ELEMENT
The node is an Element.
String name() const
Node name.
bool isZero(const BuiltInProxy< _Type > &a)
Tests if a value is exactly equal to zero.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
@ SB_AllowNull
Allows the service to be absent.
eCaseOptionReadPhase
Reading phases.
eCaseMngEventType
Types of events supported by ICaseMng.
@ BeginReadOptionsPhase2
Event generated before reading options in phase 2.
@ BeginReadOptionsPhase1
Event generated before reading options in phase 1.
Int32 Integer
Type representing an integer.
List< ICaseOptions * > CaseOptionsList
Array of dataset options.
Collection< ICaseOptions * > CaseOptionsCollection
Collection of dataset options.
double Real
Type representing a real number.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.