From 10332b6513b0756fcfe0102769f41353c0b3a54c Mon Sep 17 00:00:00 2001 From: maxence-wz Date: Wed, 22 May 2024 12:48:14 +0200 Subject: [PATCH 1/7] initial commit --- mfront-doc/include/CMakeLists.txt | 2 +- .../BehaviourDocumentationGenerator.hxx | 61 +- .../MFront/DocumentationGeneratorBase.hxx | 117 ++++ ...MaterialPropertyDocumentationGenerator.hxx | 63 ++ .../src/BehaviourDocumentationGenerator.cxx | 167 +---- mfront-doc/src/CMakeLists.txt | 4 +- mfront-doc/src/DocumentationGeneratorBase.cxx | 205 ++++++ ...MaterialPropertyDocumentationGenerator.cxx | 635 ++++++++++++++++++ mfront-doc/src/mfront-doc.cxx | 20 +- .../MFront/MaterialPropertyDescription.hxx | 9 + mfront/src/MaterialPropertyDescription.cxx | 17 +- 11 files changed, 1080 insertions(+), 220 deletions(-) create mode 100644 mfront-doc/include/MFront/DocumentationGeneratorBase.hxx create mode 100644 mfront-doc/include/MFront/MaterialPropertyDocumentationGenerator.hxx create mode 100644 mfront-doc/src/DocumentationGeneratorBase.cxx create mode 100644 mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx diff --git a/mfront-doc/include/CMakeLists.txt b/mfront-doc/include/CMakeLists.txt index 531552b0b..f7755837a 100644 --- a/mfront-doc/include/CMakeLists.txt +++ b/mfront-doc/include/CMakeLists.txt @@ -1 +1 @@ -install_mfront_header(MFront BehaviourDocumentationGenerator.hxx) +install_mfront_header(MFront DocumentationGeneratorBase.hxx BehaviourDocumentationGenerator.hxx MaterialPropertyDocumentationGenerator.hxx) diff --git a/mfront-doc/include/MFront/BehaviourDocumentationGenerator.hxx b/mfront-doc/include/MFront/BehaviourDocumentationGenerator.hxx index 7f3c4a4bc..d63e6cfa2 100644 --- a/mfront-doc/include/MFront/BehaviourDocumentationGenerator.hxx +++ b/mfront-doc/include/MFront/BehaviourDocumentationGenerator.hxx @@ -20,29 +20,15 @@ #include #include -#include "TFEL/Utilities/ArgumentParserBase.hxx" -#include "TFEL/Material/ModellingHypothesis.hxx" -#include "MFront/MFrontBase.hxx" +#include "MFront/DocumentationGeneratorBase.hxx" namespace mfront { - // forward declaration - struct AbstractBehaviourDSL; - // forward declaration - struct BehaviourDescription; - // forward declaration - struct FileDescription; - /*! * Class used by the mfront-query tool to extract information from * behaviour implementation */ - struct BehaviourDocumentationGenerator - : public tfel::utilities::ArgumentParserBase< - BehaviourDocumentationGenerator>, - public MFrontBase { - //! \brief type of documentation to be generated - enum OutputType { FULL, WEB }; + struct BehaviourDocumentationGenerator : public DocumentationGeneratorBase { /*! * build a BehaviourDocumentationGenerator object based on command line * arguments @@ -56,48 +42,19 @@ namespace mfront { std::shared_ptr, const std::string &); //! treat the requests - void exe(); + void exe() const override; //! destructor ~BehaviourDocumentationGenerator() override; private: - //! ArgumentParserBase must be a friend - friend struct tfel::utilities::ArgumentParserBase< - BehaviourDocumentationGenerator>; - //! \brief register call-backs associated with command line arguments - virtual void registerCommandLineCallBacks(); - //! treat the web argument - virtual void treatWeb(); - virtual void writeWebOutput(std::ostream &, - const BehaviourDescription &, - const FileDescription &) const; - virtual void writeFullOutput(std::ostream &, - const BehaviourDescription &, - const FileDescription &) const; - //! return the current argument - const tfel::utilities::Argument &getCurrentCommandLineArgument() - const override final; - //! treat an unknown argument - void treatUnknownArgument() override final; - //! get the version description - std::string getVersionDescription() const override final; - //! get the usage description - std::string getUsageDescription() const override final; + void writeWebOutput(std::ostream &, + const BehaviourDescription &, + const FileDescription &) const ; + void writeFullOutput(std::ostream &, + const BehaviourDescription &, + const FileDescription &) const; //! abstract behaviour dsl std::shared_ptr dsl; - //! input file name - std::string file; - //! type of ouput - OutputType otype; - //! \brief generate output on standard output - bool std_output = false; - /*! - * \brief boolean whose meaning is the following: - * - if true, the generated documentation is contained in a whole document. - * - if false, the generated documentation is contained in a section meant - * to be included in a bigger document. - */ - bool standalone = false; }; // end of struct BehaviourDocumentationGenerator } // end of namespace mfront diff --git a/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx b/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx new file mode 100644 index 000000000..204b57815 --- /dev/null +++ b/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx @@ -0,0 +1,117 @@ +/*! + * \file DocumentationGeneratorBase.hxx + * \brief + * \author Maxence Wangermez + * \date 16 avril 2024 + * \copyright Copyright (C) 2006-2024 CEA/DEN, EDF R&D. All rights + * reserved. + * This project is publicly released under either the GNU GPL Licence + * or the CECILL-A licence. A copy of thoses licences are delivered + * with the sources of TFEL. CEA or EDF may also distribute this + * project under specific licensing conditions. + */ + +#ifndef LIB_MFRONT_DOCUMENTATIONGENERATORBASE_H +#define LIB_MFRONT_DOCUMENTATIONGENERATORBASE_H + +#include +#include +#include +#include +#include + +#include "TFEL/Utilities/ArgumentParserBase.hxx" +#include "TFEL/Material/ModellingHypothesis.hxx" +#include "MFront/MFrontBase.hxx" + +namespace mfront { + + // forward declaration + struct BehaviourDescription; + // forward declaration + struct FileDescription; + + /*! + * Class used by the mfront-query tool to extract information from + * behaviour implementation + */ + struct DocumentationGeneratorBase + : public tfel::utilities::ArgumentParserBase, + public MFrontBase { + //! \brief type of documentation to be generated + enum OutputType { FULL, WEB }; + /*! + * build a DocumentationGeneratorBase object based on command line + * arguments + * \param[in] argc : number of command line arguments + * \param[in] argv : command line arguments + * \param[in] f : filename + */ + DocumentationGeneratorBase(const int, + const char *const *const, + const std::string &); + virtual void exe() const = 0; + //! destructor + ~DocumentationGeneratorBase() override; + + // Private member data + //! input file name + std::string file; + /*! + * \brief boolean whose meaning is the following: + * - if true, the generated documentation is contained in a whole document. + * - if false, the generated documentation is contained in a section meant + * to be included in a bigger document. + */ + bool standalone = false; + + //! \brief generate output on standard output + bool std_output = false; + //! type of ouput + OutputType otype; + + /*! + * internal structure gathering data from mechanical behaviour + * description + */ + struct Data { + using Hypothesis = tfel::material::ModellingHypothesis::Hypothesis; + Data(); + Data(Data &&) noexcept; + Data(const Data &); + Data &operator=(Data &&); + Data &operator=(const Data &); + ~Data() noexcept; + std::string name; + std::string type; + std::string description; + //! specific description per modelling hypothesis + std::map descriptions; + std::string externalName; + std::vector hypotheses; + unsigned short arraySize; + }; + + private: + //! ArgumentParserBase must be a friend + friend struct tfel::utilities::ArgumentParserBase< + DocumentationGeneratorBase>; + //! \brief register call-backs associated with command line arguments + virtual void registerCommandLineCallBacks(); + //! treat the web argument + virtual void treatWeb(); + //! return the current argument + const tfel::utilities::Argument &getCurrentCommandLineArgument() + const override final; + //! treat an unknown argument + void treatUnknownArgument() override final; + //! get the version description + std::string getVersionDescription() const override final; + //! get the usage description + std::string getUsageDescription() const override final; + + }; // end of struct DocumentationGeneratorBase + +} // end of namespace mfront + +#endif /* LIB_MFRONT_DOCUMENTATIONGENERATORBASE_H */ diff --git a/mfront-doc/include/MFront/MaterialPropertyDocumentationGenerator.hxx b/mfront-doc/include/MFront/MaterialPropertyDocumentationGenerator.hxx new file mode 100644 index 000000000..905889843 --- /dev/null +++ b/mfront-doc/include/MFront/MaterialPropertyDocumentationGenerator.hxx @@ -0,0 +1,63 @@ +/*! + * \file MaterialPropertyDocumentationGenerator.hxx + * \brief + * \author Maxence Wangermez + * \date 16 avril 2024 + * \copyright Copyright (C) 2006-2024 CEA/DEN, EDF R&D. All rights + * reserved. + * This project is publicly released under either the GNU GPL Licence + * or the CECILL-A licence. A copy of thoses licences are delivered + * with the sources of TFEL. CEA or EDF may also distribute this + * project under specific licensing conditions. + */ + +#ifndef LIB_MFRONT_MATERIALPROPERTYDOCUMENTATIONGENERATOR_H +#define LIB_MFRONT_MATERIALPROPERTYDOCUMENTATIONGENERATOR_H + +#include +#include +#include +#include +#include + +#include "MFront/MaterialPropertyDSL.hxx" +#include "MFront/DocumentationGeneratorBase.hxx" + +namespace mfront { + + /*! + * Class used by the mfront-query tool to extract information from + * behaviour implementation + */ + struct MaterialPropertyDocumentationGenerator + : public DocumentationGeneratorBase { + /*! + * build a MaterialPropertyDocumentationGenerator object based on command + * line arguments \param[in] argc : number of command line arguments + * \param[in] argv : command line arguments + * \param[in] d : behaviour domain specific language + * \param[in] f : behaviour domain specific language + */ + MaterialPropertyDocumentationGenerator(const int, + const char *const *const, + std::shared_ptr, + const std::string &); + //! treat the requests + void exe() const override; + //! destructor + ~MaterialPropertyDocumentationGenerator() override; + + private: + void writeWebOutput(std::ostream &, + const MaterialPropertyDescription &, + const FileDescription &) const; + void writeFullOutput(std::ostream &, + const MaterialPropertyDescription &, + const FileDescription &) const; + //! abstract behaviour dsl + std::shared_ptr dsl; + }; // end of struct MaterialPropertyDocumentationGenerator + +} // end of namespace mfront + +#endif /* LIB_MFRONT_MATERIALPROPERTYDOCUMENTATIONGENERATOR_H */ diff --git a/mfront-doc/src/BehaviourDocumentationGenerator.cxx b/mfront-doc/src/BehaviourDocumentationGenerator.cxx index a0759b219..523a83503 100644 --- a/mfront-doc/src/BehaviourDocumentationGenerator.cxx +++ b/mfront-doc/src/BehaviourDocumentationGenerator.cxx @@ -25,6 +25,7 @@ #include "MFront/VariableDescription.hxx" #include "MFront/FileDescription.hxx" #include "MFront/BehaviourDescription.hxx" +#include "MFront/DocumentationGeneratorBase.hxx" #include "MFront/BehaviourDocumentationGenerator.hxx" namespace mfront { @@ -131,36 +132,7 @@ namespace mfront { << "\\newcommand{\\ets}[1]{\\left.#1\\right|_{t+\\Delta\\,t}}\n\n"; } // end of writeStandardLatexMacros - /*! - * internal structure gathering data from mechanical behaviour - * description - */ - struct Data { - using Hypothesis = tfel::material::ModellingHypothesis::Hypothesis; - Data(); - Data(Data&&) noexcept; - Data(const Data&); - Data& operator=(Data&&); - Data& operator=(const Data&); - ~Data() noexcept; - std::string name; - std::string type; - std::string description; - //! specific description per modelling hypothesis - std::map descriptions; - std::string externalName; - std::vector hypotheses; - unsigned short arraySize; - }; - - Data::Data() = default; - Data::Data(Data&&) noexcept = default; - Data::Data(const Data&) = default; - Data& Data::operator=(Data&&) = default; - Data& Data::operator=(const Data&) = default; - Data::~Data() noexcept = default; - - static void getData(std::vector& data, + static void getData(std::vector& data, const BehaviourDescription& mb, const VariableDescriptionContainer& (BehaviourData::*m)() const, @@ -177,7 +149,7 @@ namespace mfront { } } if (pd == data.end()) { - data.push_back(Data()); + data.push_back(DocumentationGeneratorBase::Data()); pd = data.end(); --pd; pd->name = pv->name; @@ -226,13 +198,13 @@ namespace mfront { } } // end of - static std::vector getData( + static std::vector getData( const BehaviourDescription& mb, const VariableDescriptionContainer& (BehaviourData::*m)() const) { using namespace tfel::material; using namespace tfel::glossary; const auto& glossary = Glossary::getGlossary(); - auto data = std::vector{}; + auto data = std::vector{}; const auto& dh = mb.getDistinctModellingHypotheses(); for (const auto& h : dh) { getData(data, mb, m, h); @@ -297,7 +269,7 @@ namespace mfront { static void printData(std::ostream& os, const BehaviourDescription& mb, const std::string& title, - const std::vector& data, + const std::vector& data, const bool standalone, const std::string& language = "english") { using namespace tfel::material; @@ -469,136 +441,15 @@ namespace mfront { const char* const* const argv, std::shared_ptr d, const std::string& f) - : tfel::utilities::ArgumentParserBase( - argc, argv), - dsl(d), - file(f), - otype(BehaviourDocumentationGenerator::FULL) { - this->registerCommandLineCallBacks(); - this->parseArguments(); + + : DocumentationGeneratorBase(argc, argv, f), dsl(d) { // registring interfaces if (!this->interfaces.empty()) { dsl->setInterfaces(this->interfaces); } } // end of BehaviourDocumentationGenerator::BehaviourDocumentationGenerator - void BehaviourDocumentationGenerator::registerCommandLineCallBacks() { - using Parser = - tfel::utilities::ArgumentParserBase; - Parser::registerNewCallBack("--verbose", - &BehaviourDocumentationGenerator::treatVerbose, - "set verbose output", true); - this->registerNewCallBack( - "--dsl-option", &BehaviourDocumentationGenerator::treatDSLOption, - "allow to define options passed to domain specific languages", true); - this->registerNewCallBack( - "--material-property-dsl-option", - &BehaviourDocumentationGenerator::treatMaterialPropertyDSLOption, - "allow to define options passed to domain specific languages related " - "to material properties", - true); - this->registerNewCallBack( - "--behaviour-dsl-option", - &BehaviourDocumentationGenerator::treatBehaviourDSLOption, - "allow to define options passed to domain specific languages related " - "to behaviours", - true); - this->registerNewCallBack( - "--model-dsl-option", - &BehaviourDocumentationGenerator::treatModelDSLOption, - "allow to define options passed to domain specific languages related " - "to models", - true); - this->registerNewCallBack( - "--dsl-options-file", - &BehaviourDocumentationGenerator::treatDSLOptionsFile, - "allow to define options passed to domain specific languages thanks to " - "an external file in a JSON-like format", - true); - this->registerNewCallBack( - "--material-property-dsl-options-file", - &BehaviourDocumentationGenerator::treatMaterialPropertyDSLOptionsFile, - "allow to define options passed to domain specific languages related " - "to material properties thanks to an external file in a JSON-like " - "format", - true); - this->registerNewCallBack( - "--behaviour-dsl-options-file", - &BehaviourDocumentationGenerator::treatBehaviourDSLOptionsFile, - "allow to define options passed to domain specific languages related " - "to behaviours thanks to an external file in a JSON-like format", - true); - this->registerNewCallBack( - "--model-dsl-options-file", - &BehaviourDocumentationGenerator::treatModelDSLOptionsFile, - "allow to define options passed to domain specific languages related " - "to models thanks to an external file in a JSON-like format", - true); - Parser::registerNewCallBack( - "--unicode-output", - &BehaviourDocumentationGenerator::treatUnicodeOutput, - "allow/disallow unicode output", true); - Parser::registerNewCallBack( - "--include", "-I", &BehaviourDocumentationGenerator::treatSearchPath, - "add a new path at the beginning of the search paths", true); - Parser::registerNewCallBack( - "--search-path", &BehaviourDocumentationGenerator::treatSearchPath, - "add a new path at the beginning of the search paths", true); - this->registerNewCallBack( - "--madnex-search-path", - &BehaviourDocumentationGenerator::treatMadnexSearchPath, - "add a mandex file to the search paths", true); - Parser::registerCallBack( - "--standalone", - CallBack("generate a standalone document (false by default)", - [this]() noexcept { this->standalone = true; }, false)); - Parser::registerNewCallBack("--web", - &BehaviourDocumentationGenerator::treatWeb, - "output a web version of the file"); - Parser::registerCallBack( - "--std-output", "--", - CallBack("print the output ont the standard output stream", - [this]() noexcept { this->std_output = true; }, false)); - } // end of BehaviourDocumentationGenerator::registerCommandLineCallBacks - - void BehaviourDocumentationGenerator::treatUnknownArgument() { - if (!MFrontBase::treatUnknownArgumentBase()) { -#if !(defined _WIN32 || defined _WIN64 || defined __CYGWIN__) - ArgumentParserBase< - BehaviourDocumentationGenerator>::treatUnknownArgument(); -#else - auto a = static_cast( - this->getCurrentCommandLineArgument()); - std::cerr << "mfront : unsupported option '" << a << '\'' << std::endl; - exit(EXIT_FAILURE); -#endif /* __CYGWIN__ */ - } - } // end of BehaviourDocumentationGenerator::treatUnknownArgument - - const tfel::utilities::Argument& - BehaviourDocumentationGenerator::getCurrentCommandLineArgument() const { - return *(this->currentArgument); - } - - std::string BehaviourDocumentationGenerator::getVersionDescription() const { - return MFrontHeader::getHeader(); - } // end of BehaviourDocumentationGenerator::getVersionDescription - - std::string BehaviourDocumentationGenerator::getUsageDescription() const { - std::string usage("Usage : "); - usage += this->programName; - usage += " [options] [files]"; - return usage; - } // end of BehaviourDocumentationGenerator::getUsageDescription - - void BehaviourDocumentationGenerator::treatWeb() { - tfel::raise_if(this->otype != FULL, - "BehaviourDocumentationGenerator::treatWeb: " - "output type already specified"); - this->otype = WEB; - } // end of BehaviourDocumentationGenerator::treatWeb - - void BehaviourDocumentationGenerator::exe() { + void BehaviourDocumentationGenerator::exe() const { if (getVerboseMode() >= VERBOSE_LEVEL2) { getLogStream() << "Treating file '" << this->file << "'\n"; } diff --git a/mfront-doc/src/CMakeLists.txt b/mfront-doc/src/CMakeLists.txt index 8e25bd9d5..0c3ff7f71 100644 --- a/mfront-doc/src/CMakeLists.txt +++ b/mfront-doc/src/CMakeLists.txt @@ -1,6 +1,6 @@ # mfront-doc -add_executable(mfront-doc mfront-doc.cxx - BehaviourDocumentationGenerator.cxx) +add_executable(mfront-doc mfront-doc.cxx DocumentationGeneratorBase.cxx + BehaviourDocumentationGenerator.cxx MaterialPropertyDocumentationGenerator.cxx) set_property(TARGET mfront-doc PROPERTY POSITION_INDEPENDENT_CODE TRUE) target_include_directories(mfront-doc PRIVATE ${PROJECT_SOURCE_DIR}/mfront-doc/include) diff --git a/mfront-doc/src/DocumentationGeneratorBase.cxx b/mfront-doc/src/DocumentationGeneratorBase.cxx new file mode 100644 index 000000000..4a7402636 --- /dev/null +++ b/mfront-doc/src/DocumentationGeneratorBase.cxx @@ -0,0 +1,205 @@ +/*! + * \file DocumentationGeneratorBase.cxx + * \brief + * \author Maxence Wangermez + * \date 16 avril 2024 + * \copyright Copyright (C) 2006-2024 CEA/DEN, EDF R&D. All rights + * reserved. + * This project is publicly released under either the GNU GPL Licence with + * linking exception or the CECILL-A licence. A copy of thoses licences are + * delivered with the sources of TFEL. CEA or EDF may also distribute this + * project under specific licensing conditions. + */ + +#include +#include +#include + +#include "TFEL/Raise.hxx" +#include "TFEL/Glossary/Glossary.hxx" +#include "TFEL/Glossary/GlossaryEntry.hxx" +#include "TFEL/Utilities/StringAlgorithms.hxx" +#include "MFront/MFrontLogStream.hxx" +#include "MFront/MFrontHeader.hxx" +#include "MFront/AbstractBehaviourDSL.hxx" +#include "MFront/VariableDescription.hxx" +#include "MFront/FileDescription.hxx" +#include "MFront/BehaviourDescription.hxx" +#include "MFront/DocumentationGeneratorBase.hxx" + +namespace mfront { + + // map::at() is missing in ekopath standard library + template + static typename Map::mapped_type map_at(const Map& m, + const typename Map::key_type& k) { + const auto p = m.find(k); + tfel::raise_if(p == m.end(), "map_at : unknown key '" + k + "'"); + return p->second; + } + + static void writeStandardLatexMacros(std::ostream& os) { + os << "\\newcommand{\\tensor}[1]{\\underline{#1}}\n" + << "\\newcommand{\\tensorq}[1]{\\underline{\\mathbf{#1}}}\n" + << "\\newcommand{\\ust}[1]{\\underset{\\tilde{}}{\\mathbf{#1}}}\n" + << "\\newcommand{\\transpose}[1]{#1^{\\mathop{T}}}\n" + << "\\newcommand{\\tsigma}{\\underline{\\sigma}}\n" + << "\\newcommand{\\sigmaeq}{\\sigma_{\\mathrm{eq}}}\n" + << "\\newcommand{\\epsilonth}{\\epsilon^{\\mathrm{th}}}\n" + << "\\newcommand{\\tepsilonto}{\\underline{\\epsilon}^{\\mathrm{to}}}\n" + << "\\newcommand{\\tepsilonel}{\\underline{\\epsilon}^{\\mathrm{el}}}\n" + << "\\newcommand{\\tepsilonth}{\\underline{\\epsilon}^{\\mathrm{th}}}\n" + << "\\newcommand{\\tepsilonvis}{\\underline{\\epsilon}^{\\mathrm{vis}}}" + "\n" + << "\\newcommand{\\tdepsilonvis}{\\underline{\\dot{\\epsilon}}^{" + "\\mathrm{vis}}}\n" + << "\\newcommand{\\tepsilonp}{\\underline{\\epsilon}^{\\mathrm{p}}}\n" + << "\\newcommand{\\tdepsilonp}{\\underline{\\dot{\\epsilon}}^{\\mathrm{" + "p}}}\n" + << "\\newcommand{\\trace}[1]{\\mathrm{tr}\\paren{#1}}\n" + << "\\newcommand{\\Frac}[2]{{\\displaystyle \\frac{\\displaystyle " + "#1}{\\displaystyle #2}}}\n" + << "\\newcommand{\\deriv}[2]{{\\displaystyle \\frac{\\displaystyle " + "\\partial #1}{\\displaystyle \\partial #2}}}\n" + << "\\newcommand{\\dtot}{\\mathrm{d}}\n" + << "\\newcommand{\\paren}[1]{\\left(#1\\right)}\n" + << "\\newcommand{\\bts}[1]{\\left.#1\\right|_{t}}\n" + << "\\newcommand{\\mts}[1]{\\left.#1\\right|_{t+\\theta\\,\\Delta\\,t}}" + "\n" + << "\\newcommand{\\ets}[1]{\\left.#1\\right|_{t+\\Delta\\,t}}\n\n"; + } // end of writeStandardLatexMacros + + DocumentationGeneratorBase::DocumentationGeneratorBase( + const int argc, const char* const* const argv, const std::string& f) + : tfel::utilities::ArgumentParserBase(argc, + argv), + file(f), + otype(DocumentationGeneratorBase::FULL) { + this->registerCommandLineCallBacks(); + this->parseArguments(); + + } // end of DocumentationGeneratorBase::DocumentationGeneratorBase + + void DocumentationGeneratorBase::registerCommandLineCallBacks() { + using Parser = + tfel::utilities::ArgumentParserBase; + Parser::registerNewCallBack("--verbose", + &DocumentationGeneratorBase::treatVerbose, + "set verbose output", true); + this->registerNewCallBack( + "--dsl-option", &DocumentationGeneratorBase::treatDSLOption, + "allow to define options passed to domain specific languages", true); + this->registerNewCallBack( + "--material-property-dsl-option", + &DocumentationGeneratorBase::treatMaterialPropertyDSLOption, + "allow to define options passed to domain specific languages related " + "to material properties", + true); + this->registerNewCallBack( + "--behaviour-dsl-option", + &DocumentationGeneratorBase::treatBehaviourDSLOption, + "allow to define options passed to domain specific languages related " + "to behaviours", + true); + this->registerNewCallBack( + "--model-dsl-option", &DocumentationGeneratorBase::treatModelDSLOption, + "allow to define options passed to domain specific languages related " + "to models", + true); + this->registerNewCallBack( + "--dsl-options-file", &DocumentationGeneratorBase::treatDSLOptionsFile, + "allow to define options passed to domain specific languages thanks to " + "an external file in a JSON-like format", + true); + this->registerNewCallBack( + "--material-property-dsl-options-file", + &DocumentationGeneratorBase::treatMaterialPropertyDSLOptionsFile, + "allow to define options passed to domain specific languages related " + "to material properties thanks to an external file in a JSON-like " + "format", + true); + this->registerNewCallBack( + "--behaviour-dsl-options-file", + &DocumentationGeneratorBase::treatBehaviourDSLOptionsFile, + "allow to define options passed to domain specific languages related " + "to behaviours thanks to an external file in a JSON-like format", + true); + this->registerNewCallBack( + "--model-dsl-options-file", + &DocumentationGeneratorBase::treatModelDSLOptionsFile, + "allow to define options passed to domain specific languages related " + "to models thanks to an external file in a JSON-like format", + true); + Parser::registerNewCallBack("--unicode-output", + &DocumentationGeneratorBase::treatUnicodeOutput, + "allow/disallow unicode output", true); + Parser::registerNewCallBack( + "--include", "-I", &DocumentationGeneratorBase::treatSearchPath, + "add a new path at the beginning of the search paths", true); + Parser::registerNewCallBack( + "--search-path", &DocumentationGeneratorBase::treatSearchPath, + "add a new path at the beginning of the search paths", true); + this->registerNewCallBack( + "--madnex-search-path", + &DocumentationGeneratorBase::treatMadnexSearchPath, + "add a mandex file to the search paths", true); + Parser::registerCallBack( + "--standalone", + CallBack( + "generate a standalone document (false by default)", + [this]() noexcept { this->standalone = true; }, false)); + Parser::registerNewCallBack("--web", &DocumentationGeneratorBase::treatWeb, + "output a web version of the file"); + Parser::registerCallBack( + "--std-output", "--", + CallBack( + "print the output ont the standard output stream", + [this]() noexcept { this->std_output = true; }, false)); + } // end of DocumentationGeneratorBase::registerCommandLineCallBacks + + void DocumentationGeneratorBase::treatUnknownArgument() { + if (!MFrontBase::treatUnknownArgumentBase()) { +#if !(defined _WIN32 || defined _WIN64 || defined __CYGWIN__) + ArgumentParserBase::treatUnknownArgument(); +#else + auto a = static_cast( + this->getCurrentCommandLineArgument()); + std::cerr << "mfront : unsupported option '" << a << '\'' << std::endl; + exit(EXIT_FAILURE); +#endif /* __CYGWIN__ */ + } + } // end of DocumentationGeneratorBase::treatUnknownArgument + + const tfel::utilities::Argument& + DocumentationGeneratorBase::getCurrentCommandLineArgument() const { + return *(this->currentArgument); + } + + std::string DocumentationGeneratorBase::getVersionDescription() const { + return MFrontHeader::getHeader(); + } // end of DocumentationGeneratorBase::getVersionDescription + + std::string DocumentationGeneratorBase::getUsageDescription() const { + std::string usage("Usage : "); + usage += this->programName; + usage += " [options] [files]"; + return usage; + } // end of DocumentationGeneratorBase::getUsageDescription + + void DocumentationGeneratorBase::treatWeb() { + tfel::raise_if(this->otype != FULL, + "DocumentationGeneratorBase::treatWeb: " + "output type already specified"); + this->otype = WEB; + } // end of DocumentationGeneratorBase::treatWeb + + DocumentationGeneratorBase::~DocumentationGeneratorBase() = default; + + DocumentationGeneratorBase::Data::Data() = default; + DocumentationGeneratorBase::Data::Data(Data&&) noexcept = default; + DocumentationGeneratorBase::Data::Data(const Data&) = default; + DocumentationGeneratorBase::Data& DocumentationGeneratorBase::Data::operator=(Data&&) = default; + DocumentationGeneratorBase::Data& DocumentationGeneratorBase::Data::operator=(const Data&) = default; + DocumentationGeneratorBase::Data::~Data() noexcept = default; + +} // end of namespace mfront diff --git a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx new file mode 100644 index 000000000..b487492b3 --- /dev/null +++ b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx @@ -0,0 +1,635 @@ +/*! + * \file MaterialPropertyDocumentationGenerator.cxx + * \brief + * \author Maxence Wangermez + * \date 16 avril 2024 + * \copyright Copyright (C) 2006-2024 CEA/DEN, EDF R&D. All rights + * reserved. + * This project is publicly released under either the GNU GPL Licence with + * linking exception or the CECILL-A licence. A copy of thoses licences are + * delivered with the sources of TFEL. CEA or EDF may also distribute this + * project under specific licensing conditions. + */ + +#include +#include +#include + +#include "TFEL/Raise.hxx" +#include "TFEL/Glossary/Glossary.hxx" +#include "TFEL/Glossary/GlossaryEntry.hxx" +#include "TFEL/Utilities/StringAlgorithms.hxx" +#include "MFront/DSLUtilities.hxx" +#include "MFront/MFrontLogStream.hxx" +#include "MFront/MFrontHeader.hxx" +#include "MFront/AbstractBehaviourDSL.hxx" +#include "MFront/VariableDescription.hxx" +#include "MFront/FileDescription.hxx" +#include "MFront/MaterialPropertyDescription.hxx" +#include "MFront/DocumentationGeneratorBase.hxx" +#include "MFront/MaterialPropertyDocumentationGenerator.hxx" + +namespace mfront { + + // map::at() is missing in ekopath standard library + template + static typename Map::mapped_type map_at(const Map& m, + const typename Map::key_type& k) { + const auto p = m.find(k); + tfel::raise_if(p == m.end(), "map_at : unknown key '" + k + "'"); + return p->second; + } + + static std::string getCodeBlocksDocumentation( + const MaterialPropertyDescription& mpd, + const FileDescription& fd, + const bool standalone) { + const auto* const basic_title_level = standalone ? "" : "#"; + std::ostringstream out; + const auto name = mfront::getMaterialLawLibraryNameBase(mpd); + const auto& c = mpd.f; + if (!fd.description.empty()) { + out << basic_title_level << "## " << name << " description\n" // + << fd.description << "\n\n"; + } + if (getVerboseMode() >= VERBOSE_DEBUG) { + out << basic_title_level << "## " << name << " listing\n" + << '\n' + << "~~~~~~~ {.cpp}\n" + << c.body << '\n' + << "~~~~~~~ \n"; + } + return out.str(); + } + + static void writeStandardLatexMacros(std::ostream& os) { + os << "\\newcommand{\\tensor}[1]{\\underline{#1}}\n" + << "\\newcommand{\\tensorq}[1]{\\underline{\\mathbf{#1}}}\n" + << "\\newcommand{\\ust}[1]{\\underset{\\tilde{}}{\\mathbf{#1}}}\n" + << "\\newcommand{\\transpose}[1]{#1^{\\mathop{T}}}\n" + << "\\newcommand{\\tsigma}{\\underline{\\sigma}}\n" + << "\\newcommand{\\sigmaeq}{\\sigma_{\\mathrm{eq}}}\n" + << "\\newcommand{\\epsilonth}{\\epsilon^{\\mathrm{th}}}\n" + << "\\newcommand{\\tepsilonto}{\\underline{\\epsilon}^{\\mathrm{to}}}\n" + << "\\newcommand{\\tepsilonel}{\\underline{\\epsilon}^{\\mathrm{el}}}\n" + << "\\newcommand{\\tepsilonth}{\\underline{\\epsilon}^{\\mathrm{th}}}\n" + << "\\newcommand{\\tepsilonvis}{\\underline{\\epsilon}^{\\mathrm{vis}}}" + "\n" + << "\\newcommand{\\tdepsilonvis}{\\underline{\\dot{\\epsilon}}^{" + "\\mathrm{vis}}}\n" + << "\\newcommand{\\tepsilonp}{\\underline{\\epsilon}^{\\mathrm{p}}}\n" + << "\\newcommand{\\tdepsilonp}{\\underline{\\dot{\\epsilon}}^{\\mathrm{" + "p}}}\n" + << "\\newcommand{\\trace}[1]{\\mathrm{tr}\\paren{#1}}\n" + << "\\newcommand{\\Frac}[2]{{\\displaystyle \\frac{\\displaystyle " + "#1}{\\displaystyle #2}}}\n" + << "\\newcommand{\\deriv}[2]{{\\displaystyle \\frac{\\displaystyle " + "\\partial #1}{\\displaystyle \\partial #2}}}\n" + << "\\newcommand{\\dtot}{\\mathrm{d}}\n" + << "\\newcommand{\\paren}[1]{\\left(#1\\right)}\n" + << "\\newcommand{\\bts}[1]{\\left.#1\\right|_{t}}\n" + << "\\newcommand{\\mts}[1]{\\left.#1\\right|_{t+\\theta\\,\\Delta\\,t}}" + "\n" + << "\\newcommand{\\ets}[1]{\\left.#1\\right|_{t+\\Delta\\,t}}\n\n"; + } // end of writeStandardLatexMacros + +static void getData(std::vector& data, + const MaterialPropertyDescription& mpd, + const VariableDescription MaterialPropertyDescription::*m) { + // const auto& d = mpd.getBehaviourData(h); + const auto& mdata = mpd.*m; + for (auto pv = mdata.begin(); pv != mdata.end(); ++pv) { + bool found = false; + auto pd = data.begin(); + while ((pd != data.end()) && (!found)) { + found = pd->name == pv->name; + if (!found) { + ++pd; + } + } + if (pd == data.end()) { + data.push_back(DocumentationGeneratorBase::Data()); + pd = data.end(); + --pd; + pd->name = pv->name; + pd->arraySize = pv->arraySize; + pd->type = pv->type; + // pd->externalName = d.getExternalName(pv->name); + } else { + const auto uncompatible = [&pd, &pv] { + if ((pd->name != pv->name) || + // (pd->externalName != d.getExternalName(pv->name)) || + (pd->arraySize != pv->arraySize)) { + return true; + } + if (pd->type != pv->type) { + if (!((tfel::utilities::starts_with(pd->type, "struct")) && + (tfel::utilities::starts_with(pv->type, "struct")))) { + return true; + } + } + return false; + }(); + tfel::raise_if(uncompatible, + "getData: inconsistent data across " + "hypothesis for variable '" + + pd->name + "'"); + } + // if (!pv->description.empty()) { + // pd->descriptions[h] = pv->description; + // } + // pd->hypotheses.push_back(h); + } + } // end of getData + + static void getData(std::vector& data, + const MaterialPropertyDescription& mpd, + const VariableDescriptionContainer MaterialPropertyDescription::*m) { + // const auto& d = mpd.getBehaviourData(h); + const auto& mdata = mpd.*m; + for (auto pv = mdata.begin(); pv != mdata.end(); ++pv) { + bool found = false; + auto pd = data.begin(); + while ((pd != data.end()) && (!found)) { + found = pd->name == pv->name; + if (!found) { + ++pd; + } + } + if (pd == data.end()) { + data.push_back(DocumentationGeneratorBase::Data()); + pd = data.end(); + --pd; + pd->name = pv->name; + pd->arraySize = pv->arraySize; + pd->type = pv->type; + // pd->externalName = d.getExternalName(pv->name); + } else { + const auto uncompatible = [&pd, &pv] { + if ((pd->name != pv->name) || + // (pd->externalName != d.getExternalName(pv->name)) || + (pd->arraySize != pv->arraySize)) { + return true; + } + if (pd->type != pv->type) { + if (!((tfel::utilities::starts_with(pd->type, "struct")) && + (tfel::utilities::starts_with(pv->type, "struct")))) { + return true; + } + } + return false; + }(); + tfel::raise_if(uncompatible, + "getData: inconsistent data across " + "hypothesis for variable '" + + pd->name + "'"); + } + // if (!pv->description.empty()) { + // pd->descriptions[h] = pv->description; + // } + // pd->hypotheses.push_back(h); + } + } // end of getData + + static std::vector getData( + const MaterialPropertyDescription& mpd, + const VariableDescriptionContainer MaterialPropertyDescription::*m) { + using namespace tfel::material; + using namespace tfel::glossary; + const auto& glossary = Glossary::getGlossary(); + auto data = std::vector{}; + // const auto& dh = mpd.getDistinctModellingHypotheses(); + // for (const auto& h : dh) { + // } + getData(data, mpd, m); + // description deserves a specific treatment + for (auto& d : data) { + if (glossary.contains(d.externalName)) { + const auto& e = glossary.getGlossaryEntry(d.externalName); + std::ostringstream os; + os << e.getShortDescription(); + // const auto& cd = e.getDescription(); + // for(const auto & cd_pcd : cd){ + // if(!cd_pcd.empty()){ + // os << cd_pcd << '\n'; + // } + // } + d.description += os.str(); + } + auto ddc = d.descriptions.size(); + if (ddc == 1u) { + auto pd = d.descriptions.begin(); + if (!pd->second.empty()) { + if (!d.description.empty()) { + d.description += "\n"; + } + d.description += pd->second; + } + } else if (ddc != 0u) { + // Two cases: all descriptions are the same + bool b = true; + auto pd = d.descriptions.begin(); + auto pd2 = pd; + advance(pd2, 1u); + for (; (pd2 != d.descriptions.end()) && (b); ++pd2) { + b = pd->second == pd2->second; + } + if (b) { + if (!d.description.empty()) { + d.description += "\n"; + } + d.description += pd->second; + } else { + for (pd2 = pd; (pd2 != d.descriptions.end()) && (b); ++pd2) { + if (!pd2->second.empty()) { + if (!d.description.empty()) { + d.description += "\n"; + } + if (pd2->first == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { + d.description += "Default Hypothesis : " + pd2->second; + } else { + d.description += ModellingHypothesis::toString(pd2->first) + + " : " + pd2->second; + } + } + } + } + } + } + return data; + } + + static void printData( + std::ostream& os, + const MaterialPropertyDescription& mpd, + const std::string& title, + const std::vector& data, + const bool standalone, + const std::string& language = "english") { + using namespace tfel::material; + if (data.empty()) { + return; + } + const auto* const basic_title_level = standalone ? "" : "#"; + auto translations = + std::map>{}; + auto& en = translations["english"]; + auto& fr = translations["french"]; + en["variable name"] = "variable name"; + fr["variable name"] = "nom"; + en["variable type"] = "variable type"; + fr["variable type"] = "type"; + en["array size"] = "array size"; + fr["array size"] = "taille"; + en["defined for"] = "defined for"; + fr["defined for"] = "définie pour"; + en["description"] = "description"; + fr["description"] = "description"; + en["default value"] = "default value"; + fr["default value"] = "valeur par défaut"; + en["default value for"] = "default value for"; + fr["default value for"] = + "valeur par défaut pour l'hypothèse de modélsation "; + const auto& l = translations[language]; + if (getVerboseMode() >= VERBOSE_DEBUG) { + auto& log = getLogStream(); + log << "printData : begin\n"; + } + // const auto& dh = mpd.getDistinctModellingHypotheses(); + auto cbnames = std::set{}; + // for (const auto& h : dh) { + // const auto& d = mpd.getBehaviourData(h); + // const auto& cn = d.getCodeBlockNames(); + // cbnames.insert(cn.begin(), cn.end()); + // } + cbnames.insert(mfront::getMaterialLawLibraryNameBase(mpd)); + os << basic_title_level // + << "## " << title << "\n\n"; + for (const auto& d : data) { + os << "* " << d.externalName << ":\n"; + if (d.externalName != d.name) { + os << "\t+ " << map_at(l, "variable name") << ": " << d.name << '\n'; + } + os << "\t+ " << map_at(l, "variable type") << ": " << d.type << '\n'; + if (d.arraySize != 1u) { + os << "\t+ " << map_at(l, "array size") << ": " << d.arraySize << '\n'; + } + // if (d.hypotheses.size() != dh.size()) { + // os << "\t+ " << map_at(l, "defined for") << " "; + // for (auto pvh = d.hypotheses.begin(); pvh != d.hypotheses.end();) { + // os << ModellingHypothesis::toString(*pvh); + // if (++pvh != d.hypotheses.end()) { + // os << ", "; + // } + // } + // os << '\n'; + // } + if (!d.description.empty()) { + os << "\t+ " << map_at(l, "description") << ": " << d.description + << '\n'; + } + // for (const auto& h : d.hypotheses) { + // if (mpd.isParameterName(h, d.name)) { + // if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { + // os << "\t+ " << map_at(l, "default value") << ": "; + // } else { + // os << "\t+ " + // << map_at(l, "default value for") + " " + + // ModellingHypothesis::toString(h) + ": "; + // } + // if (d.type == "int") { + // os << mpd.getIntegerParameterDefaultValue(h, d.name); + // } else if (d.type == "ushort") { + // os << mpd.getUnsignedShortParameterDefaultValue(h, d.name); + // } else { + // const auto& p = + // mpd.getBehaviourData(h).getParameters().getVariable(d.name); + // if (p.arraySize == 1u) { + // os << mpd.getFloattingPointParameterDefaultValue(h, d.name); + // } else { + // for (unsigned short i = 0; i != p.arraySize;) { + // os << mpd.getFloattingPointParameterDefaultValue(h, d.name, i); + // if (++i != p.arraySize) { + // os << " "; + // } + // } + // } + // } + // os << '\n'; + // } + // } + // codes blocks referring to the current variable + auto vcb = + std::map>{}; + auto dvcb = + std::map>{}; + // for (const auto& cbname : cbnames) { + // // for (const auto& h : dh) { + // // const auto& bd = mpd.getBehaviourData(h); + // // const bool b = (bd.isIntegrationVariableName(d.name) || + // // bd.isExternalStateVariableName(d.name)); + // // if (bd.hasCode(cbname)) { + // // const auto& cb = bd.getCodeBlock(cbname); + // // if (cb.members.find(d.name) != cb.members.end()) { + // // vcb[cbname].push_back(h); + // // } + // // if (b) { + // // if (cb.members.find("d" + d.name) != cb.members.end()) { + // // dvcb[cbname].push_back(h); + // // } + // // } + // // } + // // } + // } + if (getVerboseMode() >= VERBOSE_DEBUG) { + if (!vcb.empty()) { + os << "\t+ used in "; + for (auto pc = vcb.begin(); pc != vcb.end();) { + os << pc->first; + // if (pc->second.size() != dh.size()) { + // os << " ("; + // for (auto pvh = pc->second.begin(); pvh != pc->second.end();) { + // os << ModellingHypothesis::toString(*pvh); + // if (++pvh != pc->second.end()) { + // os << ", "; + // } + // } + // os << ")"; + // } + if (++pc != vcb.end()) { + os << ", "; + } + } + os << '\n'; + } + if (!dvcb.empty()) { + os << "\t+ increment (or rate) used in "; + for (auto pc = dvcb.begin(); pc != dvcb.end();) { + os << pc->first; + // if (pc->second.size() != dh.size()) { + // os << " ("; + // for (auto pvh = pc->second.begin(); pvh != pc->second.end();) { + // os << ModellingHypothesis::toString(*pvh); + // if (++pvh != pc->second.end()) { + // os << ", "; + // } + // } + // os << ")"; + // } + if (++pc != dvcb.end()) { + os << ", "; + } + } + os << '\n'; + } + } + } + // bounds + if (getVerboseMode() >= VERBOSE_DEBUG) { + auto& log = getLogStream(); + log << "printData : end\n"; + } + } + + MaterialPropertyDocumentationGenerator:: + MaterialPropertyDocumentationGenerator( + const int argc, + const char* const* const argv, + std::shared_ptr d, + const std::string& f) + + : DocumentationGeneratorBase(argc, argv, f), dsl(d) { + // registring interfaces + if (!this->interfaces.empty()) { + dsl->setInterfaces(this->interfaces); + } + } // end of + // MaterialPropertyDocumentationGenerator::MaterialPropertyDocumentationGenerator + + void MaterialPropertyDocumentationGenerator::exe() const { + if (getVerboseMode() >= VERBOSE_LEVEL2) { + getLogStream() << "Treating file '" << this->file << "'\n"; + } + // analysing the file + this->dsl->analyseFile(this->file, this->ecmds, this->substitutions); + const auto& fd = this->dsl->getFileDescription(); + const auto& mpd = this->dsl->getMaterialPropertyDescription(); + if (getVerboseMode() >= VERBOSE_DEBUG) { + auto& log = getLogStream(); + log << "MaterialPropertyDocumentationGenerator::exe : begin\n"; + } + std::ofstream output_file; + auto& out = [&output_file, &mpd, this]() -> std::ostream& { + if (this->std_output) { + return std::cout; + } + const auto name = mfront::getMaterialLawLibraryNameBase(mpd); + output_file.open(name + ".md"); + output_file.exceptions(std::ios::badbit | std::ios::failbit); + tfel::raise_if(!output_file, + "MaterialPropertyDocumentationGenerator::exe: " + "could not open file 'src/" + + name + ".txt'"); + return output_file; + }(); + writeStandardLatexMacros(out); + if (this->otype == FULL) { + this->writeFullOutput(out, mpd, fd); + } else if (this->otype == WEB) { + this->writeWebOutput(out, mpd, fd); + } else { + tfel::raise( + "MaterialPropertyDocumentationGenerator::exe: " + "unsupported output type"); + } + if (!this->std_output) { + output_file.close(); + } + if (getVerboseMode() >= VERBOSE_DEBUG) { + getLogStream() << "MaterialPropertyDocumentationGenerator::exe : end\n"; + } + } // end of MaterialPropertyDocumentationGenerator::exe + + void MaterialPropertyDocumentationGenerator::writeWebOutput( + std::ostream& out, + const MaterialPropertyDescription& mpd, + const FileDescription& fd) const { + using namespace tfel::utilities; + out << "# " << mfront::getMaterialLawLibraryNameBase(mpd) << mpd.className << " material property description\n\n" + << "* file : " << fd.fileName << '\n' + << "* author : "; + if (!fd.authorName.empty()) { + out << fd.authorName << '\n'; + } else { + out << "(unspecified)\n"; + } + out << "* date : "; + if (!fd.date.empty()) { + out << fd.date; + } else { + out << "(unspecified)\n"; + } + // if (mpd.hasAttribute(MaterialPropertyDescription::algorithm)) { + // out << "* algorithm: " + // << mpd.getAttribute( + // MaterialPropertyDescription::algorithm) + // << '\n'; + // } + out << "\n\n"; + if (!fd.description.empty()) { + const auto d = tokenize(fd.description, '\n'); + for (const auto& l : d) { + if ((l.size() >= 2) && ((l)[0] == '*') && ((l)[1] == ' ')) { + out << l.substr(2) << '\n'; + } else { + out << l << '\n'; + } + } + } else { + out << "No description specified\n"; + } + // + std::ifstream f(this->file); + tfel::raise_if(!f, + "MaterialPropertyDocumentationGenerator::writeWebOutput: " + "can't open file '" + + this->file + "'"); + out << '\n' + << "## Source code\n" + << '\n' + << "~~~~{#" << mpd.className << " .cpp .numberLines}\n" + << f.rdbuf() << '\n' + << "~~~~\n" + << '\n'; + } // end of MaterialPropertyDocumentationGenerator::writeWebOutput + + void MaterialPropertyDocumentationGenerator::writeFullOutput( + std::ostream& out, + const MaterialPropertyDescription& mpd, + const FileDescription& fd) const { + using namespace tfel::utilities; + using namespace tfel::material; + const auto* const basic_title_level = this->standalone ? "" : "#"; + if (this->standalone) { + out << "---\n" + << "title: Description of material property " << mfront::getMaterialLawLibraryNameBase(mpd) << mpd.className << '\n'; + if (!fd.authorName.empty()) { + out << "author: " << fd.authorName << '\n'; + } + if (!fd.date.empty()) { + out << "date: " << fd.date << '\n'; + } + out << "lang: en-EN\n" + << "link-citations: true\n" + << "colorlinks: true\n" + << "figPrefixTemplate: $$i$$\n" + << "tblPrefixTemplate: $$i$$\n" + << "secPrefixTemplate: $$i$$\n" + << "eqnPrefixTemplate: ($$i$$)\n" + << "---"; + } else { + out << "# " << mfront::getMaterialLawLibraryNameBase(mpd) << '_' << mpd.className << " material property description\n\n" + << "* file: " << fd.fileName << '\n' + << "* author: "; + if (!fd.authorName.empty()) { + out << fd.authorName << '\n'; + } else { + out << "(unspecified)\n"; + } + out << "* date: "; + if (!fd.date.empty()) { + out << fd.date; + } else { + out << "(unspecified)"; + } + } + out << "\n\n"; + if (!fd.description.empty()) { + const auto d = tokenize(fd.description, '\n'); + for (const auto& l : d) { + if ((l.size() >= 2) && ((l)[0] == '*') && ((l)[1] == ' ')) { + out << l.substr(2) << '\n'; + } else { + out << l << '\n'; + } + } + } else { + out << "No description specified"; + } + out << '\n' // + << basic_title_level << "# Variables\n\n"; + // printData(out, mpd, "Material properties", + // getData(mpd, &MaterialPropertyDescription::getMaterialProperties), + // this->standalone); + // out << '\n'; + // printData(out, mpd, "State variables", + // getData(mpd, &MaterialPropertyDescription::getPersistentVariables), + // this->standalone); + // out << '\n'; + // printData( + // out, mpd, "External state variables", + // getData(mpd, &MaterialPropertyDescription::getExternalStateVariables), + // this->standalone); + out << '\n'; + if (mpd.hasParameters()) { + printData(out, mpd, "Parameters", + getData(mpd, &MaterialPropertyDescription::parameters), + this->standalone); + } + out << '\n'; + printData(out, mpd, "Inputs", + getData(mpd, &MaterialPropertyDescription::inputs), + this->standalone); + out << '\n'; + const auto code = getCodeBlocksDocumentation(mpd, fd, this->standalone); + if (!code.empty() != 0) { + out << basic_title_level // + << "# Code documentation\n\n" + << code << '\n'; + } + } // end of MaterialPropertyDocumentationGenerator::writeFullOutput + + MaterialPropertyDocumentationGenerator:: + ~MaterialPropertyDocumentationGenerator() = default; + +} // end of namespace mfront diff --git a/mfront-doc/src/mfront-doc.cxx b/mfront-doc/src/mfront-doc.cxx index 132e03e5e..4a58f2221 100644 --- a/mfront-doc/src/mfront-doc.cxx +++ b/mfront-doc/src/mfront-doc.cxx @@ -30,16 +30,19 @@ #include "MFront/InitInterfaces.hxx" #include "MFront/MFrontHeader.hxx" #include "MFront/MFrontBase.hxx" -#include "MFront/BehaviourDocumentationGenerator.hxx" #include "MFront/AbstractDSL.hxx" #include "MFront/AbstractBehaviourDSL.hxx" +#include "MFront/MaterialPropertyDSL.hxx" +#include "MFront/DocumentationGeneratorBase.hxx" +#include "MFront/BehaviourDocumentationGenerator.hxx" +#include "MFront/MaterialPropertyDocumentationGenerator.hxx" #include "MFront/PathSpecifier.hxx" #include "MFront/SearchPathsHandler.hxx" /* coverity [UNCAUGHT_EXCEPT]*/ int main(const int argc, const char* const* const argv) { using namespace mfront; - using BGen = BehaviourDocumentationGenerator; + using BGen = DocumentationGeneratorBase; initDSLs(); initInterfaces(); auto current_path_specifier = mfront::PathSpecifier{}; @@ -74,13 +77,19 @@ int main(const int argc, const char* const* const argv) { mfront::getImplementationsPaths(path_specifiers); SearchPathsHandler::addSearchPathsFromImplementationPaths(implementations); // - auto bgens = std::vector>{}; + auto bgens = std::vector>{}; + auto mpgens = std::vector>{}; for (const auto& f : implementations) { auto dsl = MFrontBase::getDSL(f); if (dsl->getTargetType() == AbstractDSL::BEHAVIOURDSL) { auto b = std::dynamic_pointer_cast(dsl); tfel::raise_if(!b, "mfront-doc: invalid dsl implementation"); - bgens.push_back(std::make_shared( + bgens.push_back(std::make_shared( + untreated_arguments.size(), untreated_arguments.data(), b, f)); + } else if (dsl->getTargetType() == AbstractDSL::MATERIALPROPERTYDSL) { + auto b = std::dynamic_pointer_cast(dsl); + tfel::raise_if(!b, "mfront-doc: invalid dsl implementation"); + mpgens.push_back(std::make_shared( untreated_arguments.size(), untreated_arguments.data(), b, f)); } else { tfel::raise("mfront-doc: unsupported dsl type"); @@ -90,6 +99,9 @@ int main(const int argc, const char* const* const argv) { for (const auto& q : bgens) { q->exe(); } + for (const auto& q : mpgens) { + q->exe(); + } #if defined _WIN32 || defined _WIN64 || defined __CYGWIN__ } catch (std::exception& e) { MessageBox(nullptr, e.what(), "mfront", 0); diff --git a/mfront/include/MFront/MaterialPropertyDescription.hxx b/mfront/include/MFront/MaterialPropertyDescription.hxx index 2e477cde0..ce4a1e0ef 100644 --- a/mfront/include/MFront/MaterialPropertyDescription.hxx +++ b/mfront/include/MFront/MaterialPropertyDescription.hxx @@ -106,6 +106,15 @@ namespace mfront { * \brief append the given code to the sources */ void appendToSources(const std::string&); + /*! + * \return true a parameter with the given name has been declared + * \param[in] n: name + */ + bool hasParameter(const std::string&) const; + /*! + * \return true if at least one parameter has been declared + */ + bool hasParameters() const; /*! * \brief register a name. * \param[in] n : name diff --git a/mfront/src/MaterialPropertyDescription.cxx b/mfront/src/MaterialPropertyDescription.cxx index 22e367e82..e449eb487 100644 --- a/mfront/src/MaterialPropertyDescription.cxx +++ b/mfront/src/MaterialPropertyDescription.cxx @@ -62,9 +62,9 @@ namespace mfront { const auto use_qt = (areQuantitiesSupported && useQuantities(mpd)) ? "true" : "false"; for (const auto& a : getScalarTypeAliases()) { - os << "using " << a << " [[maybe_unused]] = " - << "typename tfel::config::ScalarTypes<" << numeric_type << ", " - << use_qt << ">::" << a << ";\n"; + os << "using " << a + << " [[maybe_unused]] = " << "typename tfel::config::ScalarTypes<" + << numeric_type << ", " << use_qt << ">::" << a << ";\n"; } } // end of writeScalarStandardTypedefs @@ -306,6 +306,17 @@ namespace mfront { } } // end of addMaterialLaw + bool MaterialPropertyDescription::hasParameter(const std::string& v) const { + return this->parameters.contains(v); + } // end of hasParameter + + bool MaterialPropertyDescription::hasParameters() const { + if (!this->parameters.empty()) { + return true; + } + return false; + } // end of hasParameters + void MaterialPropertyDescription::reserveName(const std::string& n) { tfel::raise_if(!this->reservedNames.insert(n).second, "MaterialPropertyDescription::reserveName: " From fa181884f3a9c1dd6d3e23d5c894d703886d2448 Mon Sep 17 00:00:00 2001 From: maxence-wz Date: Wed, 22 May 2024 17:11:08 +0200 Subject: [PATCH 2/7] handle VariableDescription type for output --- ...MaterialPropertyDocumentationGenerator.cxx | 169 +++++------------- 1 file changed, 44 insertions(+), 125 deletions(-) diff --git a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx index b487492b3..5d0b2dc90 100644 --- a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx +++ b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx @@ -93,127 +93,47 @@ namespace mfront { << "\\newcommand{\\ets}[1]{\\left.#1\\right|_{t+\\Delta\\,t}}\n\n"; } // end of writeStandardLatexMacros -static void getData(std::vector& data, - const MaterialPropertyDescription& mpd, - const VariableDescription MaterialPropertyDescription::*m) { - // const auto& d = mpd.getBehaviourData(h); - const auto& mdata = mpd.*m; - for (auto pv = mdata.begin(); pv != mdata.end(); ++pv) { - bool found = false; - auto pd = data.begin(); - while ((pd != data.end()) && (!found)) { - found = pd->name == pv->name; - if (!found) { - ++pd; - } - } - if (pd == data.end()) { - data.push_back(DocumentationGeneratorBase::Data()); - pd = data.end(); - --pd; - pd->name = pv->name; - pd->arraySize = pv->arraySize; - pd->type = pv->type; - // pd->externalName = d.getExternalName(pv->name); - } else { - const auto uncompatible = [&pd, &pv] { - if ((pd->name != pv->name) || - // (pd->externalName != d.getExternalName(pv->name)) || - (pd->arraySize != pv->arraySize)) { - return true; - } - if (pd->type != pv->type) { - if (!((tfel::utilities::starts_with(pd->type, "struct")) && - (tfel::utilities::starts_with(pv->type, "struct")))) { - return true; - } - } - return false; - }(); - tfel::raise_if(uncompatible, - "getData: inconsistent data across " - "hypothesis for variable '" + - pd->name + "'"); - } - // if (!pv->description.empty()) { - // pd->descriptions[h] = pv->description; - // } - // pd->hypotheses.push_back(h); - } - } // end of getData - static void getData(std::vector& data, - const MaterialPropertyDescription& mpd, - const VariableDescriptionContainer MaterialPropertyDescription::*m) { - // const auto& d = mpd.getBehaviourData(h); - const auto& mdata = mpd.*m; - for (auto pv = mdata.begin(); pv != mdata.end(); ++pv) { - bool found = false; - auto pd = data.begin(); - while ((pd != data.end()) && (!found)) { - found = pd->name == pv->name; - if (!found) { - ++pd; - } - } - if (pd == data.end()) { - data.push_back(DocumentationGeneratorBase::Data()); - pd = data.end(); - --pd; - pd->name = pv->name; - pd->arraySize = pv->arraySize; - pd->type = pv->type; - // pd->externalName = d.getExternalName(pv->name); - } else { - const auto uncompatible = [&pd, &pv] { - if ((pd->name != pv->name) || - // (pd->externalName != d.getExternalName(pv->name)) || - (pd->arraySize != pv->arraySize)) { - return true; - } - if (pd->type != pv->type) { - if (!((tfel::utilities::starts_with(pd->type, "struct")) && - (tfel::utilities::starts_with(pv->type, "struct")))) { - return true; - } - } - return false; - }(); - tfel::raise_if(uncompatible, - "getData: inconsistent data across " - "hypothesis for variable '" + - pd->name + "'"); - } - // if (!pv->description.empty()) { - // pd->descriptions[h] = pv->description; - // } - // pd->hypotheses.push_back(h); - } + const VariableDescription& v) { + auto ndata = DocumentationGeneratorBase::Data{}; + ndata.name = v.name; + ndata.arraySize = v.arraySize; + ndata.type = v.type; + data.push_back(ndata); } // end of getData static std::vector getData( - const MaterialPropertyDescription& mpd, - const VariableDescriptionContainer MaterialPropertyDescription::*m) { + const VariableDescription& vd) { using namespace tfel::material; using namespace tfel::glossary; const auto& glossary = Glossary::getGlossary(); auto data = std::vector{}; - // const auto& dh = mpd.getDistinctModellingHypotheses(); - // for (const auto& h : dh) { - // } - getData(data, mpd, m); + getData(data, vd); + // description deserves a specific treatment + return data; + } + + static std::vector getData( + const VariableDescriptionContainer& vdc) { + using namespace tfel::material; + using namespace tfel::glossary; + const auto& glossary = Glossary::getGlossary(); + auto data = std::vector{}; + for (const auto& vd : vdc) { + getData(data, vd); + } // description deserves a specific treatment for (auto& d : data) { if (glossary.contains(d.externalName)) { const auto& e = glossary.getGlossaryEntry(d.externalName); std::ostringstream os; os << e.getShortDescription(); - // const auto& cd = e.getDescription(); - // for(const auto & cd_pcd : cd){ - // if(!cd_pcd.empty()){ - // os << cd_pcd << '\n'; - // } - // } + const auto& cd = e.getDescription(); + for (const auto& cd_pcd : cd) { + if (!cd_pcd.empty()) { + os << cd_pcd << '\n'; + } + } d.description += os.str(); } auto ddc = d.descriptions.size(); @@ -348,8 +268,8 @@ static void getData(std::vector& data, // os << mpd.getFloattingPointParameterDefaultValue(h, d.name); // } else { // for (unsigned short i = 0; i != p.arraySize;) { - // os << mpd.getFloattingPointParameterDefaultValue(h, d.name, i); - // if (++i != p.arraySize) { + // os << mpd.getFloattingPointParameterDefaultValue(h, d.name, + // i); if (++i != p.arraySize) { // os << " "; // } // } @@ -495,7 +415,8 @@ static void getData(std::vector& data, const MaterialPropertyDescription& mpd, const FileDescription& fd) const { using namespace tfel::utilities; - out << "# " << mfront::getMaterialLawLibraryNameBase(mpd) << mpd.className << " material property description\n\n" + out << "# " << mfront::getMaterialLawLibraryNameBase(mpd) << mpd.className + << " material property description\n\n" << "* file : " << fd.fileName << '\n' << "* author : "; if (!fd.authorName.empty()) { @@ -552,7 +473,9 @@ static void getData(std::vector& data, const auto* const basic_title_level = this->standalone ? "" : "#"; if (this->standalone) { out << "---\n" - << "title: Description of material property " << mfront::getMaterialLawLibraryNameBase(mpd) << mpd.className << '\n'; + << "title: Description of material property " + << mfront::getMaterialLawLibraryNameBase(mpd) << mpd.className + << '\n'; if (!fd.authorName.empty()) { out << "author: " << fd.authorName << '\n'; } @@ -568,7 +491,8 @@ static void getData(std::vector& data, << "eqnPrefixTemplate: ($$i$$)\n" << "---"; } else { - out << "# " << mfront::getMaterialLawLibraryNameBase(mpd) << '_' << mpd.className << " material property description\n\n" + out << "# " << mfront::getMaterialLawLibraryNameBase(mpd) << '_' + << mpd.className << " material property description\n\n" << "* file: " << fd.fileName << '\n' << "* author: "; if (!fd.authorName.empty()) { @@ -599,27 +523,22 @@ static void getData(std::vector& data, out << '\n' // << basic_title_level << "# Variables\n\n"; // printData(out, mpd, "Material properties", - // getData(mpd, &MaterialPropertyDescription::getMaterialProperties), + // getData(mpd, + // &MaterialPropertyDescription::getMaterialProperties), // this->standalone); + out << '\n'; + printData(out, mpd, "Output", getData(mpd.output), this->standalone); // out << '\n'; - // printData(out, mpd, "State variables", - // getData(mpd, &MaterialPropertyDescription::getPersistentVariables), + // printData(out, mpd, "Constante", + // getData(mpd, &MaterialPropertyDescription::staticVars), // this->standalone); - // out << '\n'; - // printData( - // out, mpd, "External state variables", - // getData(mpd, &MaterialPropertyDescription::getExternalStateVariables), - // this->standalone); out << '\n'; if (mpd.hasParameters()) { - printData(out, mpd, "Parameters", - getData(mpd, &MaterialPropertyDescription::parameters), + printData(out, mpd, "Parameters", getData(mpd.parameters), this->standalone); } out << '\n'; - printData(out, mpd, "Inputs", - getData(mpd, &MaterialPropertyDescription::inputs), - this->standalone); + printData(out, mpd, "Inputs", getData(mpd.inputs), this->standalone); out << '\n'; const auto code = getCodeBlocksDocumentation(mpd, fd, this->standalone); if (!code.empty() != 0) { From c843c5267c78223ca3890e3fb7e141d6a908f44c Mon Sep 17 00:00:00 2001 From: maxence-wz Date: Wed, 26 Jun 2024 09:01:13 +0200 Subject: [PATCH 3/7] WIP - handle staticVariableDescription - fix filename --- ...MaterialPropertyDocumentationGenerator.cxx | 195 ++++++++---------- 1 file changed, 88 insertions(+), 107 deletions(-) diff --git a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx index 5d0b2dc90..301280205 100644 --- a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx +++ b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx @@ -99,6 +99,19 @@ namespace mfront { ndata.name = v.name; ndata.arraySize = v.arraySize; ndata.type = v.type; + ndata.externalName = v.getExternalName(); + ndata.description = v.description; + + data.push_back(ndata); + } // end of getData + + static void getData(std::vector& data, + const StaticVariableDescription& v) { + auto ndata = DocumentationGeneratorBase::Data{}; + ndata.name = v.name; + ndata.arraySize = v.arraySize; + ndata.type = v.type; + ndata.description = v.description; data.push_back(ndata); } // end of getData @@ -106,7 +119,6 @@ namespace mfront { const VariableDescription& vd) { using namespace tfel::material; using namespace tfel::glossary; - const auto& glossary = Glossary::getGlossary(); auto data = std::vector{}; getData(data, vd); // description deserves a specific treatment @@ -179,9 +191,74 @@ namespace mfront { return data; } + static std::vector getData( + const StaticVariableDescriptionContainer& vdc) { + using namespace tfel::material; + using namespace tfel::glossary; + const auto& glossary = Glossary::getGlossary(); + auto data = std::vector{}; + for (const auto& vd : vdc) { + getData(data, vd); + } + // description deserves a specific treatment + for (auto& d : data) { + if (glossary.contains(d.externalName)) { + const auto& e = glossary.getGlossaryEntry(d.externalName); + std::ostringstream os; + os << e.getShortDescription(); + const auto& cd = e.getDescription(); + for (const auto& cd_pcd : cd) { + if (!cd_pcd.empty()) { + os << cd_pcd << '\n'; + } + } + d.description += os.str(); + } + auto ddc = d.descriptions.size(); + if (ddc == 1u) { + auto pd = d.descriptions.begin(); + if (!pd->second.empty()) { + if (!d.description.empty()) { + d.description += "\n"; + } + d.description += pd->second; + } + } else if (ddc != 0u) { + // Two cases: all descriptions are the same + bool b = true; + auto pd = d.descriptions.begin(); + auto pd2 = pd; + advance(pd2, 1u); + for (; (pd2 != d.descriptions.end()) && (b); ++pd2) { + b = pd->second == pd2->second; + } + if (b) { + if (!d.description.empty()) { + d.description += "\n"; + } + d.description += pd->second; + } else { + for (pd2 = pd; (pd2 != d.descriptions.end()) && (b); ++pd2) { + if (!pd2->second.empty()) { + if (!d.description.empty()) { + d.description += "\n"; + } + if (pd2->first == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { + d.description += "Default Hypothesis : " + pd2->second; + } else { + d.description += ModellingHypothesis::toString(pd2->first) + + " : " + pd2->second; + } + } + } + } + } + } + return data; + } + static void printData( std::ostream& os, - const MaterialPropertyDescription& mpd, const std::string& title, const std::vector& data, const bool standalone, @@ -215,14 +292,6 @@ namespace mfront { auto& log = getLogStream(); log << "printData : begin\n"; } - // const auto& dh = mpd.getDistinctModellingHypotheses(); - auto cbnames = std::set{}; - // for (const auto& h : dh) { - // const auto& d = mpd.getBehaviourData(h); - // const auto& cn = d.getCodeBlockNames(); - // cbnames.insert(cn.begin(), cn.end()); - // } - cbnames.insert(mfront::getMaterialLawLibraryNameBase(mpd)); os << basic_title_level // << "## " << title << "\n\n"; for (const auto& d : data) { @@ -234,88 +303,21 @@ namespace mfront { if (d.arraySize != 1u) { os << "\t+ " << map_at(l, "array size") << ": " << d.arraySize << '\n'; } - // if (d.hypotheses.size() != dh.size()) { - // os << "\t+ " << map_at(l, "defined for") << " "; - // for (auto pvh = d.hypotheses.begin(); pvh != d.hypotheses.end();) { - // os << ModellingHypothesis::toString(*pvh); - // if (++pvh != d.hypotheses.end()) { - // os << ", "; - // } - // } - // os << '\n'; - // } if (!d.description.empty()) { os << "\t+ " << map_at(l, "description") << ": " << d.description << '\n'; } - // for (const auto& h : d.hypotheses) { - // if (mpd.isParameterName(h, d.name)) { - // if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { - // os << "\t+ " << map_at(l, "default value") << ": "; - // } else { - // os << "\t+ " - // << map_at(l, "default value for") + " " + - // ModellingHypothesis::toString(h) + ": "; - // } - // if (d.type == "int") { - // os << mpd.getIntegerParameterDefaultValue(h, d.name); - // } else if (d.type == "ushort") { - // os << mpd.getUnsignedShortParameterDefaultValue(h, d.name); - // } else { - // const auto& p = - // mpd.getBehaviourData(h).getParameters().getVariable(d.name); - // if (p.arraySize == 1u) { - // os << mpd.getFloattingPointParameterDefaultValue(h, d.name); - // } else { - // for (unsigned short i = 0; i != p.arraySize;) { - // os << mpd.getFloattingPointParameterDefaultValue(h, d.name, - // i); if (++i != p.arraySize) { - // os << " "; - // } - // } - // } - // } - // os << '\n'; - // } - // } + // codes blocks referring to the current variable auto vcb = std::map>{}; auto dvcb = std::map>{}; - // for (const auto& cbname : cbnames) { - // // for (const auto& h : dh) { - // // const auto& bd = mpd.getBehaviourData(h); - // // const bool b = (bd.isIntegrationVariableName(d.name) || - // // bd.isExternalStateVariableName(d.name)); - // // if (bd.hasCode(cbname)) { - // // const auto& cb = bd.getCodeBlock(cbname); - // // if (cb.members.find(d.name) != cb.members.end()) { - // // vcb[cbname].push_back(h); - // // } - // // if (b) { - // // if (cb.members.find("d" + d.name) != cb.members.end()) { - // // dvcb[cbname].push_back(h); - // // } - // // } - // // } - // // } - // } if (getVerboseMode() >= VERBOSE_DEBUG) { if (!vcb.empty()) { os << "\t+ used in "; for (auto pc = vcb.begin(); pc != vcb.end();) { os << pc->first; - // if (pc->second.size() != dh.size()) { - // os << " ("; - // for (auto pvh = pc->second.begin(); pvh != pc->second.end();) { - // os << ModellingHypothesis::toString(*pvh); - // if (++pvh != pc->second.end()) { - // os << ", "; - // } - // } - // os << ")"; - // } if (++pc != vcb.end()) { os << ", "; } @@ -326,16 +328,6 @@ namespace mfront { os << "\t+ increment (or rate) used in "; for (auto pc = dvcb.begin(); pc != dvcb.end();) { os << pc->first; - // if (pc->second.size() != dh.size()) { - // os << " ("; - // for (auto pvh = pc->second.begin(); pvh != pc->second.end();) { - // os << ModellingHypothesis::toString(*pvh); - // if (++pvh != pc->second.end()) { - // os << ", "; - // } - // } - // os << ")"; - // } if (++pc != dvcb.end()) { os << ", "; } @@ -383,7 +375,9 @@ namespace mfront { if (this->std_output) { return std::cout; } - const auto name = mfront::getMaterialLawLibraryNameBase(mpd); + const auto name = mpd.material.empty() + ? mpd.className + : mpd.material + "_" + mpd.className; output_file.open(name + ".md"); output_file.exceptions(std::ios::badbit | std::ios::failbit); tfel::raise_if(!output_file, @@ -430,12 +424,6 @@ namespace mfront { } else { out << "(unspecified)\n"; } - // if (mpd.hasAttribute(MaterialPropertyDescription::algorithm)) { - // out << "* algorithm: " - // << mpd.getAttribute( - // MaterialPropertyDescription::algorithm) - // << '\n'; - // } out << "\n\n"; if (!fd.description.empty()) { const auto d = tokenize(fd.description, '\n'); @@ -522,23 +510,16 @@ namespace mfront { } out << '\n' // << basic_title_level << "# Variables\n\n"; - // printData(out, mpd, "Material properties", - // getData(mpd, - // &MaterialPropertyDescription::getMaterialProperties), - // this->standalone); out << '\n'; - printData(out, mpd, "Output", getData(mpd.output), this->standalone); - // out << '\n'; - // printData(out, mpd, "Constante", - // getData(mpd, &MaterialPropertyDescription::staticVars), - // this->standalone); + printData(out, "Inputs", getData(mpd.inputs), this->standalone); + out << '\n'; + printData(out, "Outputs", getData(mpd.output), this->standalone); out << '\n'; if (mpd.hasParameters()) { - printData(out, mpd, "Parameters", getData(mpd.parameters), - this->standalone); + printData(out, "Parameters", getData(mpd.parameters), this->standalone); } out << '\n'; - printData(out, mpd, "Inputs", getData(mpd.inputs), this->standalone); + printData(out, "Constantes", getData(mpd.staticVars), this->standalone); out << '\n'; const auto code = getCodeBlocksDocumentation(mpd, fd, this->standalone); if (!code.empty() != 0) { From b7dde3951e6a939614e4f681421895a7b9975940 Mon Sep 17 00:00:00 2001 From: maxence-wz Date: Wed, 26 Jun 2024 09:19:53 +0200 Subject: [PATCH 4/7] Describes the changes made by closing issue #535 for release-notes --- docs/web/release-notes-5.0.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/web/release-notes-5.0.md b/docs/web/release-notes-5.0.md index 11d90223d..4661c41e8 100644 --- a/docs/web/release-notes-5.0.md +++ b/docs/web/release-notes-5.0.md @@ -215,6 +215,15 @@ use the `TFEL` libraries in `C++` projects, using either the # Issues fixed +## Issue 535: [mfront-doc] add support for material properties + +Allows mfront-doc to be used with the `MaterialLaw` DSL. Example of use: + +``` +mfront-doc T91MartensiticSteel_gamma1_ROUX2007.mfront +``` +For more details, see + ## Issue 582: [cast3m interface] add explicit names and 4-letter mapping of internal variables to the castem file Adds the correspondence between variable names and the 4-letter From 0a13340cc1518c534e496c98e5bef3494ac265cc Mon Sep 17 00:00:00 2001 From: maxence-wz Date: Thu, 4 Jul 2024 10:17:43 +0200 Subject: [PATCH 5/7] update after TH review --- docs/web/release-notes-5.0.md | 7 +- .../BehaviourDocumentationGenerator.hxx | 15 +- .../MFront/DocumentationGeneratorBase.hxx | 26 +- ...MaterialPropertyDocumentationGenerator.hxx | 10 + .../src/BehaviourDocumentationGenerator.cxx | 207 +++------------ mfront-doc/src/DocumentationGeneratorBase.cxx | 24 +- ...MaterialPropertyDocumentationGenerator.cxx | 247 +++++++++--------- mfront-doc/src/mfront-doc.cxx | 12 +- 8 files changed, 220 insertions(+), 328 deletions(-) diff --git a/docs/web/release-notes-5.0.md b/docs/web/release-notes-5.0.md index 4661c41e8..e9ba3817c 100644 --- a/docs/web/release-notes-5.0.md +++ b/docs/web/release-notes-5.0.md @@ -219,9 +219,10 @@ use the `TFEL` libraries in `C++` projects, using either the Allows mfront-doc to be used with the `MaterialLaw` DSL. Example of use: -``` -mfront-doc T91MartensiticSteel_gamma1_ROUX2007.mfront -``` +~~~~{.bash} +$ mfront-doc T91MartensiticSteel_gamma1_ROUX2007.mfront +~~~~ + For more details, see ## Issue 582: [cast3m interface] add explicit names and 4-letter mapping of internal variables to the castem file diff --git a/mfront-doc/include/MFront/BehaviourDocumentationGenerator.hxx b/mfront-doc/include/MFront/BehaviourDocumentationGenerator.hxx index d63e6cfa2..9e1730177 100644 --- a/mfront-doc/include/MFront/BehaviourDocumentationGenerator.hxx +++ b/mfront-doc/include/MFront/BehaviourDocumentationGenerator.hxx @@ -46,10 +46,23 @@ namespace mfront { //! destructor ~BehaviourDocumentationGenerator() override; + struct VariableInformation + : DocumentationGeneratorBase::VariableInformationBase { + using Hypothesis = tfel::material::ModellingHypothesis::Hypothesis; + VariableInformation(); + VariableInformation(VariableInformation &&) noexcept; + VariableInformation(const VariableInformation &); + VariableInformation &operator=(VariableInformation &&); + VariableInformation &operator=(const VariableInformation &); + ~VariableInformation() noexcept; + std::map descriptions; + std::vector hypotheses; + }; + private: void writeWebOutput(std::ostream &, const BehaviourDescription &, - const FileDescription &) const ; + const FileDescription &) const; void writeFullOutput(std::ostream &, const BehaviourDescription &, const FileDescription &) const; diff --git a/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx b/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx index 204b57815..4d8619afb 100644 --- a/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx +++ b/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx @@ -21,7 +21,6 @@ #include #include "TFEL/Utilities/ArgumentParserBase.hxx" -#include "TFEL/Material/ModellingHypothesis.hxx" #include "MFront/MFrontBase.hxx" namespace mfront { @@ -69,26 +68,21 @@ namespace mfront { bool std_output = false; //! type of ouput OutputType otype; + //! \brief generate latex macros for header of output file + void writeStandardLatexMacros(std::ostream &) const; - /*! - * internal structure gathering data from mechanical behaviour - * description - */ - struct Data { - using Hypothesis = tfel::material::ModellingHypothesis::Hypothesis; - Data(); - Data(Data &&) noexcept; - Data(const Data &); - Data &operator=(Data &&); - Data &operator=(const Data &); - ~Data() noexcept; + //! \brief data structure describing a variable + struct VariableInformationBase { + VariableInformationBase(); + VariableInformationBase(VariableInformationBase &&) noexcept; + VariableInformationBase(const VariableInformationBase &); + VariableInformationBase &operator=(VariableInformationBase &&); + VariableInformationBase &operator=(const VariableInformationBase &); + ~VariableInformationBase() noexcept; std::string name; std::string type; std::string description; - //! specific description per modelling hypothesis - std::map descriptions; std::string externalName; - std::vector hypotheses; unsigned short arraySize; }; diff --git a/mfront-doc/include/MFront/MaterialPropertyDocumentationGenerator.hxx b/mfront-doc/include/MFront/MaterialPropertyDocumentationGenerator.hxx index 905889843..c6d034bac 100644 --- a/mfront-doc/include/MFront/MaterialPropertyDocumentationGenerator.hxx +++ b/mfront-doc/include/MFront/MaterialPropertyDocumentationGenerator.hxx @@ -47,6 +47,16 @@ namespace mfront { //! destructor ~MaterialPropertyDocumentationGenerator() override; + struct VariableInformation + : DocumentationGeneratorBase::VariableInformationBase { + VariableInformation(); + VariableInformation(VariableInformation &&) noexcept; + VariableInformation(const VariableInformation &); + VariableInformation &operator=(VariableInformation &&); + VariableInformation &operator=(const VariableInformation &); + ~VariableInformation() noexcept; + }; + private: void writeWebOutput(std::ostream &, const MaterialPropertyDescription &, diff --git a/mfront-doc/src/BehaviourDocumentationGenerator.cxx b/mfront-doc/src/BehaviourDocumentationGenerator.cxx index 1251a0949..3c39d3d9f 100644 --- a/mfront-doc/src/BehaviourDocumentationGenerator.cxx +++ b/mfront-doc/src/BehaviourDocumentationGenerator.cxx @@ -101,42 +101,11 @@ namespace mfront { return out.str(); } - static void writeStandardLatexMacros(std::ostream& os) { - os << "\\newcommand{\\tensor}[1]{\\underline{#1}}\n" - << "\\newcommand{\\tensorq}[1]{\\underline{\\mathbf{#1}}}\n" - << "\\newcommand{\\ust}[1]{\\underset{\\tilde{}}{\\mathbf{#1}}}\n" - << "\\newcommand{\\transpose}[1]{#1^{\\mathop{T}}}\n" - << "\\newcommand{\\tsigma}{\\underline{\\sigma}}\n" - << "\\newcommand{\\sigmaeq}{\\sigma_{\\mathrm{eq}}}\n" - << "\\newcommand{\\epsilonth}{\\epsilon^{\\mathrm{th}}}\n" - << "\\newcommand{\\tepsilonto}{\\underline{\\epsilon}^{\\mathrm{to}}}\n" - << "\\newcommand{\\tepsilonel}{\\underline{\\epsilon}^{\\mathrm{el}}}\n" - << "\\newcommand{\\tepsilonth}{\\underline{\\epsilon}^{\\mathrm{th}}}\n" - << "\\newcommand{\\tepsilonvis}{\\underline{\\epsilon}^{\\mathrm{vis}}}" - "\n" - << "\\newcommand{\\tdepsilonvis}{\\underline{\\dot{\\epsilon}}^{" - "\\mathrm{vis}}}\n" - << "\\newcommand{\\tepsilonp}{\\underline{\\epsilon}^{\\mathrm{p}}}\n" - << "\\newcommand{\\tdepsilonp}{\\underline{\\dot{\\epsilon}}^{\\mathrm{" - "p}}}\n" - << "\\newcommand{\\trace}[1]{\\mathrm{tr}\\paren{#1}}\n" - << "\\newcommand{\\Frac}[2]{{\\displaystyle \\frac{\\displaystyle " - "#1}{\\displaystyle #2}}}\n" - << "\\newcommand{\\deriv}[2]{{\\displaystyle \\frac{\\displaystyle " - "\\partial #1}{\\displaystyle \\partial #2}}}\n" - << "\\newcommand{\\dtot}{\\mathrm{d}}\n" - << "\\newcommand{\\paren}[1]{\\left(#1\\right)}\n" - << "\\newcommand{\\bts}[1]{\\left.#1\\right|_{t}}\n" - << "\\newcommand{\\mts}[1]{\\left.#1\\right|_{t+\\theta\\,\\Delta\\,t}}" - "\n" - << "\\newcommand{\\ets}[1]{\\left.#1\\right|_{t+\\Delta\\,t}}\n\n"; - } // end of writeStandardLatexMacros - - static void getData(std::vector& data, - const BehaviourDescription& mb, - const VariableDescriptionContainer& (BehaviourData::*m)() - const, - const tfel::material::ModellingHypothesis::Hypothesis h) { + static void getData( + std::vector& data, + const BehaviourDescription& mb, + const VariableDescriptionContainer& (BehaviourData::*m)() const, + const tfel::material::ModellingHypothesis::Hypothesis h) { const auto& d = mb.getBehaviourData(h); const auto& mdata = (d.*m)(); for (auto pv = mdata.begin(); pv != mdata.end(); ++pv) { @@ -149,7 +118,7 @@ namespace mfront { } } if (pd == data.end()) { - data.push_back(DocumentationGeneratorBase::Data()); + data.push_back(BehaviourDocumentationGenerator::VariableInformation()); pd = data.end(); --pd; pd->name = pv->name; @@ -198,13 +167,14 @@ namespace mfront { } } // end of - static std::vector getData( - const BehaviourDescription& mb, - const VariableDescriptionContainer& (BehaviourData::*m)() const) { + static std::vector + getData(const BehaviourDescription& mb, + const VariableDescriptionContainer& (BehaviourData::*m)() const) { using namespace tfel::material; using namespace tfel::glossary; const auto& glossary = Glossary::getGlossary(); - auto data = std::vector{}; + auto data = + std::vector{}; const auto& dh = mb.getDistinctModellingHypotheses(); for (const auto& h : dh) { getData(data, mb, m, h); @@ -266,12 +236,14 @@ namespace mfront { return data; } - static void printData(std::ostream& os, - const BehaviourDescription& mb, - const std::string& title, - const std::vector& data, - const bool standalone, - const std::string& language = "english") { + static void printData( + std::ostream& os, + const BehaviourDescription& mb, + const std::string& title, + const std::vector& + data, + const bool standalone, + const std::string& language = "english") { using namespace tfel::material; if (data.empty()) { return; @@ -451,125 +423,7 @@ namespace mfront { } } // end of BehaviourDocumentationGenerator::BehaviourDocumentationGenerator - void BehaviourDocumentationGenerator::registerCommandLineCallBacks() { - using Parser = - tfel::utilities::ArgumentParserBase; - Parser::registerNewCallBack("--verbose", - &BehaviourDocumentationGenerator::treatVerbose, - "set verbose output", true); - this->registerNewCallBack( - "--dsl-option", &BehaviourDocumentationGenerator::treatDSLOption, - "allow to define options passed to domain specific languages", true); - this->registerNewCallBack( - "--material-property-dsl-option", - &BehaviourDocumentationGenerator::treatMaterialPropertyDSLOption, - "allow to define options passed to domain specific languages related " - "to material properties", - true); - this->registerNewCallBack( - "--behaviour-dsl-option", - &BehaviourDocumentationGenerator::treatBehaviourDSLOption, - "allow to define options passed to domain specific languages related " - "to behaviours", - true); - this->registerNewCallBack( - "--model-dsl-option", - &BehaviourDocumentationGenerator::treatModelDSLOption, - "allow to define options passed to domain specific languages related " - "to models", - true); - this->registerNewCallBack( - "--dsl-options-file", - &BehaviourDocumentationGenerator::treatDSLOptionsFile, - "allow to define options passed to domain specific languages thanks to " - "an external file in a JSON-like format", - true); - this->registerNewCallBack( - "--material-property-dsl-options-file", - &BehaviourDocumentationGenerator::treatMaterialPropertyDSLOptionsFile, - "allow to define options passed to domain specific languages related " - "to material properties thanks to an external file in a JSON-like " - "format", - true); - this->registerNewCallBack( - "--behaviour-dsl-options-file", - &BehaviourDocumentationGenerator::treatBehaviourDSLOptionsFile, - "allow to define options passed to domain specific languages related " - "to behaviours thanks to an external file in a JSON-like format", - true); - this->registerNewCallBack( - "--model-dsl-options-file", - &BehaviourDocumentationGenerator::treatModelDSLOptionsFile, - "allow to define options passed to domain specific languages related " - "to models thanks to an external file in a JSON-like format", - true); - Parser::registerNewCallBack( - "--unicode-output", - &BehaviourDocumentationGenerator::treatUnicodeOutput, - "allow/disallow unicode output", true); - Parser::registerNewCallBack( - "--include", "-I", &BehaviourDocumentationGenerator::treatSearchPath, - "add a new path at the beginning of the search paths", true); - Parser::registerNewCallBack( - "--search-path", &BehaviourDocumentationGenerator::treatSearchPath, - "add a new path at the beginning of the search paths", true); - this->registerNewCallBack( - "--madnex-search-path", - &BehaviourDocumentationGenerator::treatMadnexSearchPath, - "add a mandex file to the search paths", true); - Parser::registerCallBack( - "--standalone", - CallBack( - "generate a standalone document (false by default)", - [this]() noexcept { this->standalone = true; }, false)); - Parser::registerNewCallBack("--web", - &BehaviourDocumentationGenerator::treatWeb, - "output a web version of the file"); - Parser::registerCallBack( - "--std-output", "--", - CallBack( - "print the output ont the standard output stream", - [this]() noexcept { this->std_output = true; }, false)); - } // end of BehaviourDocumentationGenerator::registerCommandLineCallBacks - - void BehaviourDocumentationGenerator::treatUnknownArgument() { - if (!MFrontBase::treatUnknownArgumentBase()) { -#if !(defined _WIN32 || defined _WIN64 || defined __CYGWIN__) - ArgumentParserBase< - BehaviourDocumentationGenerator>::treatUnknownArgument(); -#else - auto a = static_cast( - this->getCurrentCommandLineArgument()); - std::cerr << "mfront : unsupported option '" << a << '\'' << std::endl; - exit(EXIT_FAILURE); -#endif /* __CYGWIN__ */ - } - } // end of BehaviourDocumentationGenerator::treatUnknownArgument - - const tfel::utilities::Argument& - BehaviourDocumentationGenerator::getCurrentCommandLineArgument() const { - return *(this->currentArgument); - } - - std::string BehaviourDocumentationGenerator::getVersionDescription() const { - return MFrontHeader::getHeader(); - } // end of BehaviourDocumentationGenerator::getVersionDescription - - std::string BehaviourDocumentationGenerator::getUsageDescription() const { - std::string usage("Usage : "); - usage += this->programName; - usage += " [options] [files]"; - return usage; - } // end of BehaviourDocumentationGenerator::getUsageDescription - - void BehaviourDocumentationGenerator::treatWeb() { - tfel::raise_if(this->otype != FULL, - "BehaviourDocumentationGenerator::treatWeb: " - "output type already specified"); - this->otype = WEB; - } // end of BehaviourDocumentationGenerator::treatWeb - - void BehaviourDocumentationGenerator::exe() { + void BehaviourDocumentationGenerator::exe() const { if (getVerboseMode() >= VERBOSE_LEVEL2) { getLogStream() << "Treating file '" << this->file << "'\n"; } @@ -597,7 +451,7 @@ namespace mfront { name + ".txt'"); return output_file; }(); - writeStandardLatexMacros(out); + DocumentationGeneratorBase::writeStandardLatexMacros(out); if (this->otype == FULL) { this->writeFullOutput(out, mb, fd); } else if (this->otype == WEB) { @@ -758,9 +612,24 @@ namespace mfront { out << basic_title_level // << "# Code documentation\n\n" << code << '\n'; - } - } // end of BehaviourDocumentationGenerator::writeFullOutput + } + } // end of BehaviourDocumentationGenerator::writeFullOutput BehaviourDocumentationGenerator::~BehaviourDocumentationGenerator() = default; + BehaviourDocumentationGenerator::VariableInformation::VariableInformation() = + default; + BehaviourDocumentationGenerator::VariableInformation::VariableInformation( + VariableInformation&&) noexcept = default; + BehaviourDocumentationGenerator::VariableInformation::VariableInformation( + const VariableInformation&) = default; + BehaviourDocumentationGenerator::VariableInformation& + BehaviourDocumentationGenerator::VariableInformation::operator=( + VariableInformation&&) = default; + BehaviourDocumentationGenerator::VariableInformation& + BehaviourDocumentationGenerator::VariableInformation::operator=( + const VariableInformation&) = default; + BehaviourDocumentationGenerator::VariableInformation:: + ~VariableInformation() noexcept = default; + } // end of namespace mfront diff --git a/mfront-doc/src/DocumentationGeneratorBase.cxx b/mfront-doc/src/DocumentationGeneratorBase.cxx index 4a7402636..be2a294f0 100644 --- a/mfront-doc/src/DocumentationGeneratorBase.cxx +++ b/mfront-doc/src/DocumentationGeneratorBase.cxx @@ -38,7 +38,8 @@ namespace mfront { return p->second; } - static void writeStandardLatexMacros(std::ostream& os) { + void DocumentationGeneratorBase::writeStandardLatexMacros( + std::ostream& os) const { os << "\\newcommand{\\tensor}[1]{\\underline{#1}}\n" << "\\newcommand{\\tensorq}[1]{\\underline{\\mathbf{#1}}}\n" << "\\newcommand{\\ust}[1]{\\underset{\\tilde{}}{\\mathbf{#1}}}\n" @@ -195,11 +196,18 @@ namespace mfront { DocumentationGeneratorBase::~DocumentationGeneratorBase() = default; - DocumentationGeneratorBase::Data::Data() = default; - DocumentationGeneratorBase::Data::Data(Data&&) noexcept = default; - DocumentationGeneratorBase::Data::Data(const Data&) = default; - DocumentationGeneratorBase::Data& DocumentationGeneratorBase::Data::operator=(Data&&) = default; - DocumentationGeneratorBase::Data& DocumentationGeneratorBase::Data::operator=(const Data&) = default; - DocumentationGeneratorBase::Data::~Data() noexcept = default; - + DocumentationGeneratorBase::VariableInformationBase:: + VariableInformationBase() = default; + DocumentationGeneratorBase::VariableInformationBase::VariableInformationBase( + VariableInformationBase&&) noexcept = default; + DocumentationGeneratorBase::VariableInformationBase::VariableInformationBase( + const VariableInformationBase&) = default; + DocumentationGeneratorBase::VariableInformationBase& + DocumentationGeneratorBase::VariableInformationBase::operator=( + VariableInformationBase&&) = default; + DocumentationGeneratorBase::VariableInformationBase& + DocumentationGeneratorBase::VariableInformationBase::operator=( + const VariableInformationBase&) = default; + DocumentationGeneratorBase::VariableInformationBase:: + ~VariableInformationBase() noexcept = default; } // end of namespace mfront diff --git a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx index 301280205..16c5e149a 100644 --- a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx +++ b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx @@ -62,40 +62,11 @@ namespace mfront { return out.str(); } - static void writeStandardLatexMacros(std::ostream& os) { - os << "\\newcommand{\\tensor}[1]{\\underline{#1}}\n" - << "\\newcommand{\\tensorq}[1]{\\underline{\\mathbf{#1}}}\n" - << "\\newcommand{\\ust}[1]{\\underset{\\tilde{}}{\\mathbf{#1}}}\n" - << "\\newcommand{\\transpose}[1]{#1^{\\mathop{T}}}\n" - << "\\newcommand{\\tsigma}{\\underline{\\sigma}}\n" - << "\\newcommand{\\sigmaeq}{\\sigma_{\\mathrm{eq}}}\n" - << "\\newcommand{\\epsilonth}{\\epsilon^{\\mathrm{th}}}\n" - << "\\newcommand{\\tepsilonto}{\\underline{\\epsilon}^{\\mathrm{to}}}\n" - << "\\newcommand{\\tepsilonel}{\\underline{\\epsilon}^{\\mathrm{el}}}\n" - << "\\newcommand{\\tepsilonth}{\\underline{\\epsilon}^{\\mathrm{th}}}\n" - << "\\newcommand{\\tepsilonvis}{\\underline{\\epsilon}^{\\mathrm{vis}}}" - "\n" - << "\\newcommand{\\tdepsilonvis}{\\underline{\\dot{\\epsilon}}^{" - "\\mathrm{vis}}}\n" - << "\\newcommand{\\tepsilonp}{\\underline{\\epsilon}^{\\mathrm{p}}}\n" - << "\\newcommand{\\tdepsilonp}{\\underline{\\dot{\\epsilon}}^{\\mathrm{" - "p}}}\n" - << "\\newcommand{\\trace}[1]{\\mathrm{tr}\\paren{#1}}\n" - << "\\newcommand{\\Frac}[2]{{\\displaystyle \\frac{\\displaystyle " - "#1}{\\displaystyle #2}}}\n" - << "\\newcommand{\\deriv}[2]{{\\displaystyle \\frac{\\displaystyle " - "\\partial #1}{\\displaystyle \\partial #2}}}\n" - << "\\newcommand{\\dtot}{\\mathrm{d}}\n" - << "\\newcommand{\\paren}[1]{\\left(#1\\right)}\n" - << "\\newcommand{\\bts}[1]{\\left.#1\\right|_{t}}\n" - << "\\newcommand{\\mts}[1]{\\left.#1\\right|_{t+\\theta\\,\\Delta\\,t}}" - "\n" - << "\\newcommand{\\ets}[1]{\\left.#1\\right|_{t+\\Delta\\,t}}\n\n"; - } // end of writeStandardLatexMacros - - static void getData(std::vector& data, - const VariableDescription& v) { - auto ndata = DocumentationGeneratorBase::Data{}; + static void getData( + std::vector& + data, + const VariableDescription& v) { + auto ndata = MaterialPropertyDocumentationGenerator::VariableInformation{}; ndata.name = v.name; ndata.arraySize = v.arraySize; ndata.type = v.type; @@ -105,9 +76,11 @@ namespace mfront { data.push_back(ndata); } // end of getData - static void getData(std::vector& data, - const StaticVariableDescription& v) { - auto ndata = DocumentationGeneratorBase::Data{}; + static void getData( + std::vector& + data, + const StaticVariableDescription& v) { + auto ndata = MaterialPropertyDocumentationGenerator::VariableInformation{}; ndata.name = v.name; ndata.arraySize = v.arraySize; ndata.type = v.type; @@ -115,22 +88,26 @@ namespace mfront { data.push_back(ndata); } // end of getData - static std::vector getData( - const VariableDescription& vd) { + static std::vector< + MaterialPropertyDocumentationGenerator::VariableInformation> + getData(const VariableDescription& vd) { using namespace tfel::material; using namespace tfel::glossary; - auto data = std::vector{}; + auto data = std::vector< + MaterialPropertyDocumentationGenerator::VariableInformation>{}; getData(data, vd); // description deserves a specific treatment return data; } - static std::vector getData( - const VariableDescriptionContainer& vdc) { + static std::vector< + MaterialPropertyDocumentationGenerator::VariableInformation> + getData(const VariableDescriptionContainer& vdc) { using namespace tfel::material; using namespace tfel::glossary; const auto& glossary = Glossary::getGlossary(); - auto data = std::vector{}; + auto data = std::vector< + MaterialPropertyDocumentationGenerator::VariableInformation>{}; for (const auto& vd : vdc) { getData(data, vd); } @@ -148,55 +125,57 @@ namespace mfront { } d.description += os.str(); } - auto ddc = d.descriptions.size(); - if (ddc == 1u) { - auto pd = d.descriptions.begin(); - if (!pd->second.empty()) { - if (!d.description.empty()) { - d.description += "\n"; - } - d.description += pd->second; - } - } else if (ddc != 0u) { - // Two cases: all descriptions are the same - bool b = true; - auto pd = d.descriptions.begin(); - auto pd2 = pd; - advance(pd2, 1u); - for (; (pd2 != d.descriptions.end()) && (b); ++pd2) { - b = pd->second == pd2->second; - } - if (b) { - if (!d.description.empty()) { - d.description += "\n"; - } - d.description += pd->second; - } else { - for (pd2 = pd; (pd2 != d.descriptions.end()) && (b); ++pd2) { - if (!pd2->second.empty()) { - if (!d.description.empty()) { - d.description += "\n"; - } - if (pd2->first == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { - d.description += "Default Hypothesis : " + pd2->second; - } else { - d.description += ModellingHypothesis::toString(pd2->first) + - " : " + pd2->second; - } - } - } - } - } + // auto ddc = d.descriptions.size(); + // if (ddc == 1u) { + // auto pd = d.descriptions.begin(); + // if (!pd->second.empty()) { + // if (!d.description.empty()) { + // d.description += "\n"; + // } + // d.description += pd->second; + // } + // } else if (ddc != 0u) { + // // Two cases: all descriptions are the same + // bool b = true; + // auto pd = d.descriptions.begin(); + // auto pd2 = pd; + // advance(pd2, 1u); + // for (; (pd2 != d.descriptions.end()) && (b); ++pd2) { + // b = pd->second == pd2->second; + // } + // if (b) { + // if (!d.description.empty()) { + // d.description += "\n"; + // } + // d.description += pd->second; + // } else { + // for (pd2 = pd; (pd2 != d.descriptions.end()) && (b); ++pd2) { + // if (!pd2->second.empty()) { + // if (!d.description.empty()) { + // d.description += "\n"; + // } + // if (pd2->first == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { + // d.description += "Default Hypothesis : " + pd2->second; + // } else { + // d.description += ModellingHypothesis::toString(pd2->first) + + // " : " + pd2->second; + // } + // } + // } + // } + // } } return data; } - static std::vector getData( - const StaticVariableDescriptionContainer& vdc) { + static std::vector< + MaterialPropertyDocumentationGenerator::VariableInformation> + getData(const StaticVariableDescriptionContainer& vdc) { using namespace tfel::material; using namespace tfel::glossary; const auto& glossary = Glossary::getGlossary(); - auto data = std::vector{}; + auto data = std::vector< + MaterialPropertyDocumentationGenerator::VariableInformation>{}; for (const auto& vd : vdc) { getData(data, vd); } @@ -214,45 +193,45 @@ namespace mfront { } d.description += os.str(); } - auto ddc = d.descriptions.size(); - if (ddc == 1u) { - auto pd = d.descriptions.begin(); - if (!pd->second.empty()) { - if (!d.description.empty()) { - d.description += "\n"; - } - d.description += pd->second; - } - } else if (ddc != 0u) { - // Two cases: all descriptions are the same - bool b = true; - auto pd = d.descriptions.begin(); - auto pd2 = pd; - advance(pd2, 1u); - for (; (pd2 != d.descriptions.end()) && (b); ++pd2) { - b = pd->second == pd2->second; - } - if (b) { - if (!d.description.empty()) { - d.description += "\n"; - } - d.description += pd->second; - } else { - for (pd2 = pd; (pd2 != d.descriptions.end()) && (b); ++pd2) { - if (!pd2->second.empty()) { - if (!d.description.empty()) { - d.description += "\n"; - } - if (pd2->first == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { - d.description += "Default Hypothesis : " + pd2->second; - } else { - d.description += ModellingHypothesis::toString(pd2->first) + - " : " + pd2->second; - } - } - } - } - } + // auto ddc = d.descriptions.size(); + // if (ddc == 1u) { + // auto pd = d.descriptions.begin(); + // if (!pd->second.empty()) { + // if (!d.description.empty()) { + // d.description += "\n"; + // } + // d.description += pd->second; + // } + // } else if (ddc != 0u) { + // // Two cases: all descriptions are the same + // bool b = true; + // auto pd = d.descriptions.begin(); + // auto pd2 = pd; + // advance(pd2, 1u); + // for (; (pd2 != d.descriptions.end()) && (b); ++pd2) { + // b = pd->second == pd2->second; + // } + // if (b) { + // if (!d.description.empty()) { + // d.description += "\n"; + // } + // d.description += pd->second; + // } else { + // for (pd2 = pd; (pd2 != d.descriptions.end()) && (b); ++pd2) { + // if (!pd2->second.empty()) { + // if (!d.description.empty()) { + // d.description += "\n"; + // } + // if (pd2->first == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { + // d.description += "Default Hypothesis : " + pd2->second; + // } else { + // d.description += ModellingHypothesis::toString(pd2->first) + + // " : " + pd2->second; + // } + // } + // } + // } + // } } return data; } @@ -260,7 +239,8 @@ namespace mfront { static void printData( std::ostream& os, const std::string& title, - const std::vector& data, + const std::vector< + MaterialPropertyDocumentationGenerator::VariableInformation>& data, const bool standalone, const std::string& language = "english") { using namespace tfel::material; @@ -386,7 +366,7 @@ namespace mfront { name + ".txt'"); return output_file; }(); - writeStandardLatexMacros(out); + DocumentationGeneratorBase::writeStandardLatexMacros(out); if (this->otype == FULL) { this->writeFullOutput(out, mpd, fd); } else if (this->otype == WEB) { @@ -532,4 +512,19 @@ namespace mfront { MaterialPropertyDocumentationGenerator:: ~MaterialPropertyDocumentationGenerator() = default; + MaterialPropertyDocumentationGenerator::VariableInformation:: + VariableInformation() = default; + MaterialPropertyDocumentationGenerator::VariableInformation:: + VariableInformation(VariableInformation&&) noexcept = default; + MaterialPropertyDocumentationGenerator::VariableInformation:: + VariableInformation(const VariableInformation&) = default; + MaterialPropertyDocumentationGenerator::VariableInformation& + MaterialPropertyDocumentationGenerator::VariableInformation::operator=( + VariableInformation&&) = default; + MaterialPropertyDocumentationGenerator::VariableInformation& + MaterialPropertyDocumentationGenerator::VariableInformation::operator=( + const VariableInformation&) = default; + MaterialPropertyDocumentationGenerator::VariableInformation:: + ~VariableInformation() noexcept = default; + } // end of namespace mfront diff --git a/mfront-doc/src/mfront-doc.cxx b/mfront-doc/src/mfront-doc.cxx index 4a58f2221..09a009dd6 100644 --- a/mfront-doc/src/mfront-doc.cxx +++ b/mfront-doc/src/mfront-doc.cxx @@ -42,7 +42,6 @@ /* coverity [UNCAUGHT_EXCEPT]*/ int main(const int argc, const char* const* const argv) { using namespace mfront; - using BGen = DocumentationGeneratorBase; initDSLs(); initInterfaces(); auto current_path_specifier = mfront::PathSpecifier{}; @@ -77,8 +76,10 @@ int main(const int argc, const char* const* const argv) { mfront::getImplementationsPaths(path_specifiers); SearchPathsHandler::addSearchPathsFromImplementationPaths(implementations); // - auto bgens = std::vector>{}; - auto mpgens = std::vector>{}; + auto bgens = + std::vector>{}; + auto mpgens = + std::vector>{}; for (const auto& f : implementations) { auto dsl = MFrontBase::getDSL(f); if (dsl->getTargetType() == AbstractDSL::BEHAVIOURDSL) { @@ -89,8 +90,9 @@ int main(const int argc, const char* const* const argv) { } else if (dsl->getTargetType() == AbstractDSL::MATERIALPROPERTYDSL) { auto b = std::dynamic_pointer_cast(dsl); tfel::raise_if(!b, "mfront-doc: invalid dsl implementation"); - mpgens.push_back(std::make_shared( - untreated_arguments.size(), untreated_arguments.data(), b, f)); + mpgens.push_back( + std::make_shared( + untreated_arguments.size(), untreated_arguments.data(), b, f)); } else { tfel::raise("mfront-doc: unsupported dsl type"); } From bac9d58bc11544d9008eb28b05e59de398366618 Mon Sep 17 00:00:00 2001 From: maxence-wz Date: Fri, 5 Jul 2024 11:37:30 +0200 Subject: [PATCH 6/7] A few adjustments - convert writeStandardLatexMacros to static function - small change of the layout of the output file --- .../MFront/DocumentationGeneratorBase.hxx | 2 +- mfront-doc/src/DocumentationGeneratorBase.cxx | 3 +-- ...MaterialPropertyDocumentationGenerator.cxx | 20 +++++++++++-------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx b/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx index 4d8619afb..effc95bd7 100644 --- a/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx +++ b/mfront-doc/include/MFront/DocumentationGeneratorBase.hxx @@ -69,7 +69,7 @@ namespace mfront { //! type of ouput OutputType otype; //! \brief generate latex macros for header of output file - void writeStandardLatexMacros(std::ostream &) const; + static void writeStandardLatexMacros(std::ostream &); //! \brief data structure describing a variable struct VariableInformationBase { diff --git a/mfront-doc/src/DocumentationGeneratorBase.cxx b/mfront-doc/src/DocumentationGeneratorBase.cxx index be2a294f0..3bd6e008d 100644 --- a/mfront-doc/src/DocumentationGeneratorBase.cxx +++ b/mfront-doc/src/DocumentationGeneratorBase.cxx @@ -38,8 +38,7 @@ namespace mfront { return p->second; } - void DocumentationGeneratorBase::writeStandardLatexMacros( - std::ostream& os) const { + void DocumentationGeneratorBase::writeStandardLatexMacros(std::ostream& os) { os << "\\newcommand{\\tensor}[1]{\\underline{#1}}\n" << "\\newcommand{\\tensorq}[1]{\\underline{\\mathbf{#1}}}\n" << "\\newcommand{\\ust}[1]{\\underset{\\tilde{}}{\\mathbf{#1}}}\n" diff --git a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx index 16c5e149a..dccae4c8e 100644 --- a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx +++ b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx @@ -486,21 +486,25 @@ namespace mfront { } } } else { - out << "No description specified"; + out << "No description specified\n"; } - out << '\n' // - << basic_title_level << "# Variables\n\n"; - out << '\n'; + + out << '\n' << basic_title_level << "# Variables\n\n"; + printData(out, "Inputs", getData(mpd.inputs), this->standalone); out << '\n'; + printData(out, "Outputs", getData(mpd.output), this->standalone); - out << '\n'; - if (mpd.hasParameters()) { - printData(out, "Parameters", getData(mpd.parameters), this->standalone); + + if (!areParametersTreatedAsStaticVariables(mpd)) { + if (mpd.hasParameters()) { + out << '\n'; + printData(out, "Parameters", getData(mpd.parameters), this->standalone); + } } out << '\n'; printData(out, "Constantes", getData(mpd.staticVars), this->standalone); - out << '\n'; + const auto code = getCodeBlocksDocumentation(mpd, fd, this->standalone); if (!code.empty() != 0) { out << basic_title_level // From df68ce77b9a6bcec864086c084d643cba0e22eba Mon Sep 17 00:00:00 2001 From: maxence-wz Date: Fri, 5 Jul 2024 20:00:05 +0200 Subject: [PATCH 7/7] delete comments and add a test if there is no input --- ...MaterialPropertyDocumentationGenerator.cxx | 84 +------------------ 1 file changed, 4 insertions(+), 80 deletions(-) diff --git a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx index dccae4c8e..f20ae279a 100644 --- a/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx +++ b/mfront-doc/src/MaterialPropertyDocumentationGenerator.cxx @@ -125,45 +125,6 @@ namespace mfront { } d.description += os.str(); } - // auto ddc = d.descriptions.size(); - // if (ddc == 1u) { - // auto pd = d.descriptions.begin(); - // if (!pd->second.empty()) { - // if (!d.description.empty()) { - // d.description += "\n"; - // } - // d.description += pd->second; - // } - // } else if (ddc != 0u) { - // // Two cases: all descriptions are the same - // bool b = true; - // auto pd = d.descriptions.begin(); - // auto pd2 = pd; - // advance(pd2, 1u); - // for (; (pd2 != d.descriptions.end()) && (b); ++pd2) { - // b = pd->second == pd2->second; - // } - // if (b) { - // if (!d.description.empty()) { - // d.description += "\n"; - // } - // d.description += pd->second; - // } else { - // for (pd2 = pd; (pd2 != d.descriptions.end()) && (b); ++pd2) { - // if (!pd2->second.empty()) { - // if (!d.description.empty()) { - // d.description += "\n"; - // } - // if (pd2->first == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { - // d.description += "Default Hypothesis : " + pd2->second; - // } else { - // d.description += ModellingHypothesis::toString(pd2->first) + - // " : " + pd2->second; - // } - // } - // } - // } - // } } return data; } @@ -193,45 +154,6 @@ namespace mfront { } d.description += os.str(); } - // auto ddc = d.descriptions.size(); - // if (ddc == 1u) { - // auto pd = d.descriptions.begin(); - // if (!pd->second.empty()) { - // if (!d.description.empty()) { - // d.description += "\n"; - // } - // d.description += pd->second; - // } - // } else if (ddc != 0u) { - // // Two cases: all descriptions are the same - // bool b = true; - // auto pd = d.descriptions.begin(); - // auto pd2 = pd; - // advance(pd2, 1u); - // for (; (pd2 != d.descriptions.end()) && (b); ++pd2) { - // b = pd->second == pd2->second; - // } - // if (b) { - // if (!d.description.empty()) { - // d.description += "\n"; - // } - // d.description += pd->second; - // } else { - // for (pd2 = pd; (pd2 != d.descriptions.end()) && (b); ++pd2) { - // if (!pd2->second.empty()) { - // if (!d.description.empty()) { - // d.description += "\n"; - // } - // if (pd2->first == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { - // d.description += "Default Hypothesis : " + pd2->second; - // } else { - // d.description += ModellingHypothesis::toString(pd2->first) + - // " : " + pd2->second; - // } - // } - // } - // } - // } } return data; } @@ -491,8 +413,10 @@ namespace mfront { out << '\n' << basic_title_level << "# Variables\n\n"; - printData(out, "Inputs", getData(mpd.inputs), this->standalone); - out << '\n'; + if (!mpd.inputs.empty()) { + printData(out, "Inputs", getData(mpd.inputs), this->standalone); + out << '\n'; + } printData(out, "Outputs", getData(mpd.output), this->standalone);