Base.hpp 13.7 KB
Newer Older
GILLES Sebastien's avatar
GILLES Sebastien committed
1 2 3 4 5 6 7 8 9 10 11 12 13
/*!
//
// \file
//
//
// Created by Sebastien Gilles <sebastien.gilles@inria.fr> on the Wed, 14 Aug 2013 15:09:11 +0200
// Copyright (c) Inria. All rights reserved.
//
// \ingroup UtilitiesGroup
// \addtogroup UtilitiesGroup
// \{
*/

14

15 16
#ifndef MOREFEM_x_UTILITIES_x_INPUT_DATA_x_BASE_HPP_
# define MOREFEM_x_UTILITIES_x_INPUT_DATA_x_BASE_HPP_
17 18 19 20 21 22


# include <vector>
# include <string>
# include <cassert>
# include <tuple>
23
# include <type_traits>
24

25 26 27 28 29 30 31
# include "ThirdParty/IncludeWithoutWarning/Mpi/Mpi.hpp"
# include "ThirdParty/Wrappers/Mpi/Mpi.hpp"

# include "Utilities/Containers/Tuple.hpp"
# include "Utilities/Filesystem/File.hpp"
# include "Utilities/Filesystem/Folder.hpp"
# include "Utilities/String/String.hpp"
32
# include "Utilities/Environment/Environment.hpp"
33
# include "Utilities/LuaOptionFile/LuaOptionFile.hpp"
34
# include "Utilities/InputData/Extract.hpp"
35 36 37
# include "Utilities/InputData/Exceptions/InputData.hpp"
# include "Utilities/InputData/Internal/Subtuple/Subtuple.hpp"
# include "Utilities/InputData/Internal/TupleIteration/TupleIteration.hpp"
38
# include "Utilities/Mpi/Mpi.hpp"
39 40


41
namespace MoReFEM
42
{
43

44 45 46

    namespace Utilities
    {
47

48

49 50 51
        /// \namespace MoReFEM::Utilities::InputDataNS
        /// \brief Namespace dedicated to InputData.
        namespace InputDataNS
52
        {
53 54


55 56 57 58 59 60 61
            /*!
             * \brief Whether a field found in the file but not referenced in the tuple yields an exception or not.
             *
             * Should be 'yes' most of the time; I have introduced the 'no' option for cases in which we need only
             * a handful of parameters shared by all models for post-processing purposes (namely mesh-related ones).
             */
            enum class DoTrackUnusedFields { yes, no };
62

63

64 65 66 67
            // ============================
            // Forward declarations.
            // ============================

68 69
            template<class ObjectT>
            struct Extract;
70 71


72 73 74 75
            // ============================
            // End of forward declarations.
            // ============================

76

77

78
            /*!
GILLES Sebastien's avatar
GILLES Sebastien committed
79
             * \brief Provides all the mechanisms to read the input parameters and hold their values.
80
             *
81
             * As it names hints, it is intended to be a base class for a user-defined class which will deals
GILLES Sebastien's avatar
GILLES Sebastien committed
82
             * with the input parameters specific to the user problem.
83
             *
84
             * \tparam DerivedT Derived CRTP class.
85
             * \tparam TupleT A tuple which should include a class for each input parameter to consider in the file.
86
             * The class for each input parameter should derive from InputData::Crtp::InputData and defines several
GILLES Sebastien's avatar
GILLES Sebastien committed
87
             * static methods such as Description(), NameInFile() or Section(). Compiler won't let you not define one
88
             * of those anyway; to see an example of such a class see in Core/InputData or in MoReFEM documentation.
89
             *
90
             * \internal <b><tt>[internal]</tt></b> It should be a specialization of InputData; however I didn't manage to make it
91
             * a template template parameter that works both on clang and gcc.
92
             */
93
            template<class DerivedT, class TupleT>
94
            class Base : public ::MoReFEM::Crtp::CrtpMpi<Base<DerivedT, TupleT>>
95
            {
96

97
            public:
98 99


100
                //! Friendship.
101 102
                template<class ObjectT>
                friend struct Extract;
103

104

105
            public:
106

107
                //! Mpi parent.
108
                using mpi_parent = ::MoReFEM::Crtp::CrtpMpi<Base<DerivedT, TupleT>>;
109

GILLES Sebastien's avatar
GILLES Sebastien committed
110
                //! The underlying tuple type.
111
                using Tuple = TupleT;
112

113 114
                //! Size of the tuple.
                static constexpr std::size_t Size();
115

116
                //! Special members.
117
                //@{
118

119 120 121
                /*!
                 * \brief Constructor.
                 *
122
                 * \copydetails doxygen_hide_mpi_param
123
                 * \param[in] filename Name of the Lua input parameter list to be read.
124 125 126 127
                 * \param[in] do_track_unused_fields Whether a field found in the file but not referenced in the tuple
                 * yields an exception or not. Should be 'yes' most of the time; I have introduced the 'no' option for
                 * cases in which we need only a handful of parameters shared by all models for post-processing
                 * purposes (namely mesh-related ones).
128
                 */
129
                explicit Base(const std::string& filename,
130
                              const Wrappers::Mpi& mpi,
131
                              DoTrackUnusedFields do_track_unused_fields = DoTrackUnusedFields::yes);
132

133 134
                //! \copydoc doxygen_hide_copy_constructor
                Base(const Base& rhs) = delete;
135

136 137
                //! \copydoc doxygen_hide_move_constructor
                Base(Base&& rhs) = delete;
138

139
                //! \copydoc doxygen_hide_copy_affectation
140
                Base& operator=(const Base& rhs) = delete;
141

142
                //! \copydoc doxygen_hide_move_affectation
143
                Base& operator=(Base&& rhs) = delete;
144

145

146 147
                //! Destructor.
                ~Base();
148
                //@}
149 150


151 152 153 154
                /*!
                 * \brief Print the list of input parameter that weren't used in the program.
                 *
                 * This method is dedicated to be called at destruction, but when using OpenMPI it is rather uneasy
155
                 * to make it called in the destructor due to racing conditions (error if MPI_Finalize() has already
156 157 158 159 160
                 * been called.
                 *
                 * So this method should be called at the very end of your program if you want the information
                 * it gives.
                 *
161 162
                 * \copydoc doxygen_hide_stream_inout
                 * If nothing added then all input parameters were used.
163
                 *
164
                 * \internal <b><tt>[internal]</tt></b> This method collects the data from all mpi processors; the list is therefore ensured to
165 166 167
                 * be exhaustive.
                 *
                 */
168
                void PrintUnused(std::ostream& stream) const;
169

170
                //! Get the path to the input data file.
171
                //! \return Path to the input data file.
172
                const std::string& GetInputFile() const;
173

174
            private:
175 176


177
                /*!
GILLES Sebastien's avatar
GILLES Sebastien committed
178 179
                 * \brief Helper function used to extract quantity from the tuple.
                 *
180
                 * This should not be used directly by a user; ExtractValue class deals with it with a more
181 182
                 * user-friendly interface (no pesky template keyword to add!).
                 *
183
                 * \tparam InputDataT InputData class used to store the wanted input parameter.
GILLES Sebastien's avatar
GILLES Sebastien committed
184
                 * \tparam CountAsUsedT Whether the call to the methods counts as an effective use of the input
185
                 * parameter in the program. See CountAsUsed for more details; default value is fine
GILLES Sebastien's avatar
GILLES Sebastien committed
186
                 * in almost all cases.
187 188
                 *
                 * \return The requested element in the tuple. It is either copied by value or a const reference.
189
                 */
190 191
                template<class InputDataT, CountAsUsed CountAsUsedT = CountAsUsed::yes>
                typename Utilities::ConstRefOrValue<typename InputDataT::return_type>::type
192
                ReadHelper() const;
193

194

195
                /*!
196 197
                 * \brief Helper function used to extract a value from a vector element from the tuple.
                 *
198
                 * This should not be used directly by a user; Extract class deals with it with a more
199
                 * user-friendly interface (no pesky template keyword to add!).
GILLES Sebastien's avatar
GILLES Sebastien committed
200 201
                 *
                 * When an input parameter is a vector, this method may be used to fetch an element of this vector.
202 203
                 *
                 * \param[in] index Index in the vector of the quantity fetched.
GILLES Sebastien's avatar
GILLES Sebastien committed
204
                 * \tparam CountAsUsedT See ReadHelper().
205 206
                 *
                 * \return The requested element in the tuple. It is either copied by value or a const reference.
207
                 */
208 209
                template<class InputDataT, CountAsUsed CountAsUsedT = CountAsUsed::yes>
                typename Utilities::ConstRefOrValue<typename InputDataT::return_type::value_type>::type
210
                ReadHelper(unsigned int index) const;
211 212


213
                /*!
GILLES Sebastien's avatar
GILLES Sebastien committed
214
                 * \brief Helper function used to extract the size of a vector input parameter.
215
                 *
216 217
                 * \return Size of the vector read as input parameter.
                 *
218
                 */
219
                template<class InputDataT, CountAsUsed CountAsUsedT = CountAsUsed::yes>
220
                unsigned int ReadHelperNumber() const;
221

222 223 224


                /*!
225 226
                 * \brief Helper function used to handle a folder path: in case it doesn't exist, it can be
                 * created or an exception might be thrown (depending on the policy chosen).
227
                 *
228
                 * \return The requested element in the tuple. This string is afterwards interpreted as a folder;
229 230
                 * \a UnexistentFolderPolicyT policy tells what to do when the folder doesn't exist.
                 *
231
                 */
232 233 234 235 236
                template
                <
                    class InputDataT,
                    UnexistentFolderPolicy UnexistentFolderPolicyT = UnexistentFolderPolicy::create
                >
237
                std::string ReadHelperFolder() const;
238 239


240
                /*!
241
                 * \brief Helper function used to handle a path: it is basically handled as a mere string, except
242 243
                 * that environment variables are replaced on the fly if they respect the format ${...}.
                 *
244 245 246 247
                 * \warning Contrary to what the const subject (there to give the same interface whatever the string input
                 * parameter is), this method might modify the value stored in the tuple. On first call all environment
                 * variables are replaced, and what is stored afterwards is the result after the substitution.
                 *
248 249
                 * A specialized version for folder also exist (ReadHelperFolder()).
                 *
250
                 * For instance "${HOME}/Codes/MoReFEM" will be resolved on a Mac in /Users/ *username* /Codes/MoReFEM.
251 252 253
                 *
                 * \return The requested element in the tuple.
                 */
254
                template<class InputDataT>
255 256
                std::string ReadHelperPath() const;

257 258


259
            private:
260 261

                /*!
262
                 * \brief Ensure all input parameters in \a SubTupleT address vectors with the same size.
263 264 265 266
                 */
                template<class SubTupleT>
                void EnsureSameLength() const;

267 268


269
                /*!
270 271
                 * \brief Throw an exception if there is a duplicate in the keys.
                 *
272
                 * The key for an InputData A class is given by free function InputDataKey<A>().
273
                 *
274 275
                 * As these keys are what is used by \a LuaOptionFile to read the value, it is important not to use
                 * the same for two parameters.
276
                 *
277
                 * An additional bonus is that a same InputData class put twice in the tuple will also trigger this
278
                 * exception.
279
                 */
280 281 282 283
                void CheckNoDuplicateKeysInTuple() const;


                /*!
284 285
                 * \brief Check no input parameter present in the Lua file is actually not known by the input parameter
                 * file tuple.
286
                 *
287
                 * \param[in] filename Path to the input file.
288
                 * \param[in] lua_option_file The object that helps interpreting the content of the Lua file.
289
                 * \param[in] do_track_unused_fields See constructor.
290
                 *
291
                 */
292 293 294
                void CheckUnboundInputData(const std::string& filename,
                                          LuaOptionFile& lua_option_file,
                                           DoTrackUnusedFields do_track_unused_fields) const;
295

296
            public:
297

298
                //! Accessor to the underlying tuple.
299
                //! \return Underlying tuple.
300
                const auto& GetTuple() const;
301

GILLES Sebastien's avatar
GILLES Sebastien committed
302 303
            private:

304 305 306
                //! Number of elements in the tuple.
                enum { tuple_size_ = std::tuple_size<Tuple>::value };

GILLES Sebastien's avatar
GILLES Sebastien committed
307 308 309
                //! The tuple that actually stores all the relevant quantities for the problem.
                Tuple tuple_;

310 311
                //! Path of the input data file.
                std::string input_data_file_;
312

313
                //! Helper object to iterate upon the tuple (including the in-depth sections).
314
                using tuple_iteration = Internal::InputDataNS::TupleIteration<TupleT, 0, tuple_size_>;
315

316
            };
317 318 319


            /*!
320
             * \brief Create a default input file, with all relevant input parameters provided in \a TupleT.
321
             *
322
             * If a default parameter is provided in InputData class, it will be written in the file, otherwise
323 324 325 326 327
             * a filler text will be written to remind it should be filled.
             *
             * \tparam TupleT including all the input parameters we want to consider.
             *
             * \param[in] path Path to the file that will contain the result. An exception is thrown if the path is invalid.
328 329 330 331
             */
            template<class TupleT>
            void CreateDefaultInputFile(const std::string& path);

332

333
        } //  namespace InputDataNS
334 335


336
    } // namespace Utilities
337

338

339
} // namespace MoReFEM
340 341


342 343 344
/// @} // addtogroup UtilitiesGroup


345 346
# include "Utilities/InputData/Internal/ExtractParameter/ExtractParameter.hpp"
# include "Utilities/InputData/Base.hxx"
347 348


349
#endif // MOREFEM_x_UTILITIES_x_INPUT_DATA_x_BASE_HPP_