MoReFEMData.hxx 9.62 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, 21 Jan 2015 15:50:06 +0100
// Copyright (c) Inria. All rights reserved.
//
// \ingroup CoreGroup
// \addtogroup CoreGroup
// \{
*/

14

15 16
#ifndef MOREFEM_x_CORE_x_MO_RE_F_E_M_DATA_x_MO_RE_F_E_M_DATA_HXX_
# define MOREFEM_x_CORE_x_MO_RE_F_E_M_DATA_x_MO_RE_F_E_M_DATA_HXX_
17 18


19
namespace MoReFEM
20
{
21

22

23 24
    template
    <
25
        class InputDataT,
26
        program_type ProgramTypeT,
27
        Utilities::InputDataNS::DoTrackUnusedFields DoTrackUnusedFieldsT,
28
        class AdditionalCommandLineArgumentsPolicyT
29
    >
30
    MoReFEMData<InputDataT, ProgramTypeT, DoTrackUnusedFieldsT, AdditionalCommandLineArgumentsPolicyT>
31
    ::MoReFEMData(int argc, char** argv)
32
    {
33
        Internal::PetscNS::RAII::CreateOrGetInstance(__FILE__, __LINE__, argc, argv);
34

35 36 37
        const auto ptr = std::is_same<AdditionalCommandLineArgumentsPolicyT, std::nullptr_t>()
                        ? nullptr
                        : this;
38

39 40
        try
        {
41

42
            Internal::MoReFEMDataNS::overwrite_directory do_overwrite_directory;
43

44 45 46 47 48
            std::string input_data_file =
                Internal::MoReFEMDataNS::ParseCommandLine
                    <ProgramTypeT, AdditionalCommandLineArgumentsPolicyT>(argc, argv,
                                                                          do_overwrite_directory,
                                                                          ptr);
49

50
            decltype(auto) mpi = GetMpi();
51

52
            Internal::MoReFEMDataNS::DefineEnvironmentVariable(mpi);
53

54 55 56
            if (mpi.IsRootProcessor())
                // Stops the program after creating it for root processor.
                Internal::MoReFEMDataNS::CreateIfNotExisting<typename InputDataT::Tuple>(input_data_file);
57

58
            Internal::MoReFEMDataNS::CheckExistingForAllRank(mpi, input_data_file);
59

60 61 62 63
            // We can be here only if the file exists...
            input_data_ = std::make_unique<InputDataT>(input_data_file,
                                                       mpi,
                                                       DoTrackUnusedFieldsT);
64

65

66

67 68 69 70 71 72 73
            namespace ipl = Utilities::InputDataNS;
            using Result = InputDataNS::Result;

            {
                std::string path = ipl::Extract<Result::OutputDirectory>::Path(*input_data_);

                FilesystemNS::behaviour directory_behaviour;
74

75 76 77 78 79 80 81 82
                if constexpr(ProgramTypeT == program_type::model)
                    directory_behaviour = do_overwrite_directory == Internal::MoReFEMDataNS::overwrite_directory::yes
                                         ? FilesystemNS::behaviour::overwrite
                                         : FilesystemNS::behaviour::ask;
                else if constexpr(ProgramTypeT == program_type::test)
                    directory_behaviour = FilesystemNS::behaviour::overwrite;
                else if constexpr(ProgramTypeT == program_type::post_processing)
                    directory_behaviour = FilesystemNS::behaviour::read;
83

84 85 86 87
                result_directory_ = std::make_unique<FilesystemNS::Directory>(mpi,
                                                                              path,
                                                                              directory_behaviour,
                                                                              __FILE__, __LINE__);
88

89 90
                // Parallelism is an optional field: it might not be present in the Lua file (for tests for instance
                // it is not meaningful).
91 92 93 94 95 96 97 98 99 100
                if constexpr (InputDataT::template Find<InputDataNS::Parallelism>())
                    parallelism_ = std::make_unique<Internal::Parallelism>(mpi, *input_data_, directory_behaviour);
            }

            mpi.Barrier();

            InitTimeKeepLog(GetResultDirectory());

            const auto& binary_output = ipl::Extract<Result::BinaryOutput>::Value(*input_data_);
            Utilities::OutputFormat::CreateOrGetInstance(__FILE__, __LINE__, binary_output);
DIAZ Jerome's avatar
#20  
DIAZ Jerome committed
101 102 103 104 105 106
            
            if constexpr (InputDataT::template Find<InputDataNS::Solid::CheckInvertedElements>())
            {
                const auto& do_check_inverted_elements = ipl::Extract<InputDataNS::Solid::CheckInvertedElements>
                                                            ::Value(*input_data_);
                
107 108
                MoReFEM::Internal::MoReFEMDataNS::CheckInvertedElements
                                                ::CreateOrGetInstance(__FILE__, __LINE__, do_check_inverted_elements);
DIAZ Jerome's avatar
#20  
DIAZ Jerome committed
109
            }
110 111 112
			else
			{
				// Create it nonetheless - but will trigger an exception if the value is called.
113
                MoReFEM::Internal::MoReFEMDataNS::CheckInvertedElements::CreateOrGetInstance(__FILE__, __LINE__);
114
			}
115 116 117 118 119 120
        }
        catch(const ExceptionNS::GracefulExit& e)
        {
            std::cout << e.what() << std::endl;
            throw;
        }
121
    }
122 123


124 125
    template
    <
126
        class InputDataT,
127
        program_type ProgramTypeT,
128
        Utilities::InputDataNS::DoTrackUnusedFields DoTrackUnusedFieldsT,
129
        class AdditionalCommandLineArgumentsPolicyT
130
    >
131
    MoReFEMData<InputDataT, ProgramTypeT, DoTrackUnusedFieldsT, AdditionalCommandLineArgumentsPolicyT>
132
    ::~MoReFEMData()
133
    {
134

135 136
        // Flush all the standard outputs. Catch all exceptions: exceptions in destructor are naughty!
        const auto& mpi = GetMpi();
137

138 139
        try
        {
140 141
            Wrappers::Petsc::SynchronizedFlush(mpi, stdout, __FILE__, __LINE__);
            Wrappers::Petsc::SynchronizedFlush(mpi, stderr, __FILE__, __LINE__);
142 143 144
        }
        catch (const std::exception& e)
        {
145
            std::cerr << "Untimely exception caught in ~MoReFEMData(): " << e.what() << std::endl;
146 147 148 149 150 151
            assert(false && "No exception in destructors!");
        }
        catch (...)
        {
            assert(false && "No exception in destructors!");
        }
152

153
        input_data_ = nullptr;
154

155
        mpi.Barrier(); // to better handle the possible MpiAbort() on one of the branch...
156
    }
157 158


159 160
    template
    <
161
        class InputDataT,
162
        program_type ProgramTypeT,
163
        Utilities::InputDataNS::DoTrackUnusedFields DoTrackUnusedFieldsT,
164
        class AdditionalCommandLineArgumentsPolicyT
165
    >
166
    inline const Wrappers::Mpi&
167
    MoReFEMData<InputDataT, ProgramTypeT, DoTrackUnusedFieldsT, AdditionalCommandLineArgumentsPolicyT>
168
    ::GetMpi() const noexcept
169
    {
170 171
        decltype(auto) raii = Internal::PetscNS::RAII::GetInstance(__FILE__, __LINE__);
        return raii.GetMpi();
172
    }
173 174


175 176
    template
    <
177
        class InputDataT,
178
        program_type ProgramTypeT,
179
        Utilities::InputDataNS::DoTrackUnusedFields DoTrackUnusedFieldsT,
180
        class AdditionalCommandLineArgumentsPolicyT
181
    >
182 183
    const InputDataT&
    MoReFEMData<InputDataT, ProgramTypeT, DoTrackUnusedFieldsT, AdditionalCommandLineArgumentsPolicyT>
184
    ::GetInputData() const noexcept
185
    {
186 187
        assert(!(!input_data_));
        return *input_data_;
188
    }
189 190


191 192
    template
    <
193
        class InputDataT,
194
        program_type ProgramTypeT,
195
        Utilities::InputDataNS::DoTrackUnusedFields DoTrackUnusedFieldsT,
196
        class AdditionalCommandLineArgumentsPolicyT
197
    >
198
    const FilesystemNS::Directory&
199
    MoReFEMData<InputDataT, ProgramTypeT, DoTrackUnusedFieldsT, AdditionalCommandLineArgumentsPolicyT>
200
    ::GetResultDirectory() const noexcept
201
    {
202 203
        assert(!(!result_directory_));
        return *result_directory_;
204 205 206
    }


207 208 209
    template
    <
        class InputDataT,
210
        program_type ProgramTypeT,
211 212 213
        Utilities::InputDataNS::DoTrackUnusedFields DoTrackUnusedFieldsT,
        class AdditionalCommandLineArgumentsPolicyT
    >
214 215
    const Internal::Parallelism*
    MoReFEMData<InputDataT, ProgramTypeT, DoTrackUnusedFieldsT, AdditionalCommandLineArgumentsPolicyT>
216 217
    ::GetParallelismPtr() const noexcept
    {
218 219 220
        if (!parallelism_)
            return nullptr;
        
221 222 223 224
        return parallelism_.get();
    }


225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
    template
    <
        class InputDataT,
        program_type ProgramTypeT,
        Utilities::InputDataNS::DoTrackUnusedFields DoTrackUnusedFieldsT,
        class AdditionalCommandLineArgumentsPolicyT
    >
    const Internal::Parallelism&
    MoReFEMData<InputDataT, ProgramTypeT, DoTrackUnusedFieldsT, AdditionalCommandLineArgumentsPolicyT>
    ::GetParallelism() const noexcept
    {
        assert(!(!parallelism_));
        return *parallelism_;
    }


241 242 243 244 245 246 247 248 249 250 251
    template<class MoReFEMDataT>
    void PrecomputeExit(const MoReFEMDataT& morefem_data)
    {
        const auto parallelism_ptr = morefem_data.GetParallelismPtr();

        if (!(!parallelism_ptr))
        {
            switch (parallelism_ptr->GetParallelismStrategy())
            {
                case Advanced::parallelism_strategy::precompute:
                {
252 253 254 255
                    if (morefem_data.GetMpi().IsRootProcessor())
                        std::cout << "The parallelism elements have been precomputed; the program will now end."
                            << std::endl;

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
                    throw ExceptionNS::GracefulExit(__FILE__, __LINE__);
                }
                case Advanced::parallelism_strategy::parallel:
                case Advanced::parallelism_strategy::run_from_preprocessed:
                case Advanced::parallelism_strategy::parallel_no_write:
                    break;
                case Advanced::parallelism_strategy::none:
                {
                    assert(false && "Should not be possible (if so parallelism_ptr should have been nullptr).");
                    exit(EXIT_FAILURE);
                }
            }
        }
    }


272
} // namespace MoReFEM
273 274


275 276 277
/// @} // addtogroup CoreGroup


278
#endif // MOREFEM_x_CORE_x_MO_RE_F_E_M_DATA_x_MO_RE_F_E_M_DATA_HXX_