primaryvariableswitchadapter.hh 5.58 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/****************************************************************************
 *   See the file COPYING for full copying permissions.                      *
 *                                                                           *
 *   This program is free software: you can redistribute it and/or modify    *
 *   it under the terms of the GNU General Public License as published by    *
 *   the Free Software Foundation, either version 3 of the License, or       *
 *   (at your option) any later version.                                     *
 *                                                                           *
 *   This program is distributed in the hope that it will be useful,         *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
 *   GNU General Public License for more details.                            *
 *                                                                           *
 *   You should have received a copy of the GNU General Public License       *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
 *****************************************************************************/
/*!
 * \file
 * \ingroup Nonlinear
 * \brief An adapter for the Newton to manage models with primary variable switch
 */
#ifndef DUMUX_NONLINEAR_PRIMARY_VARIABLE_SWITCH_ADAPTER_HH
#define DUMUX_NONLINEAR_PRIMARY_VARIABLE_SWITCH_ADAPTER_HH

#include <memory>
#include <dune/common/std/type_traits.hh>
29
#include <dumux/common/parameters.hh>
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

namespace Dumux {
namespace Detail {

//! helper aliases to extract a primary variable switch from the VolumeVariables (if defined, yields int otherwise)
template<class Variables>
using DetectPVSwitch = typename Variables::VolumeVariables::PrimaryVariableSwitch;

template<class Variables>
using GetPVSwitch = Dune::Std::detected_or<int, DetectPVSwitch, Variables>;

template<class Variables>
using PrimaryVariableSwitch = typename GetPVSwitch<Variables>::type;

} // end namespace Detail

/*!
 * \ingroup Nonlinear
 * \brief Helper boolean to check if the given variables involve primary variable switching.
 */
template<class Variables>
inline constexpr bool hasPriVarsSwitch = typename Detail::GetPVSwitch<Variables>::value_t();

/*!
 * \ingroup Nonlinear
 * \brief An adapter for the Newton to manage models with primary variable switch
 */
template <class Variables, bool isValid = hasPriVarsSwitch<Variables>>
class PrimaryVariableSwitchAdapter
{
    using PrimaryVariableSwitch = typename Detail::PrimaryVariableSwitch<Variables>;

public:
    PrimaryVariableSwitchAdapter(const std::string& paramGroup = "")
    {
        const int priVarSwitchVerbosity = getParamFromGroup<int>(paramGroup, "PrimaryVariableSwitch.Verbosity", 1);
        priVarSwitch_ = std::make_unique<PrimaryVariableSwitch>(priVarSwitchVerbosity);
    }

    /*!
     * \brief Initialize the privar switch
     */
    template<class SolutionVector>
    void initialize(SolutionVector& sol, Variables& vars)
    {
        priVarSwitch_->reset(sol.size());
        priVarsSwitchedInLastIteration_ = false;
        const auto& problem = vars.curGridVolVars().problem();
        const auto& gridGeometry = problem.gridGeometry();
        priVarSwitch_->updateDirichletConstraints(problem, gridGeometry, vars, sol);
    }

    /*!
     * \brief Switch primary variables if necessary
     */
    template<class SolutionVector>
    void invoke(SolutionVector& uCurrentIter, Variables& vars)
    {
        // update the variable switch (returns true if the pri vars at at least one dof were switched)
        // for disabled grid variable caching
        const auto& problem = vars.curGridVolVars().problem();
        const auto& gridGeometry = problem.gridGeometry();

        // invoke the primary variable switch
        priVarsSwitchedInLastIteration_ = priVarSwitch_->update(uCurrentIter, vars, problem, gridGeometry);
        if (priVarsSwitchedInLastIteration_)
        {
            for (const auto& element : elements(gridGeometry.gridView()))
            {
                // if the volume variables are cached globally, we need to update those where the primary variables have been switched
                priVarSwitch_->updateSwitchedVolVars(problem, element, gridGeometry, vars, uCurrentIter);

                // if the flux variables are cached globally, we need to update those where the primary variables have been switched
                priVarSwitch_->updateSwitchedFluxVarsCache(problem, element, gridGeometry, vars, uCurrentIter);
            }
        }
    }

    /*!
     * \brief Whether the primary variables have been switched in the last call to invoke
     */
    bool switched() const
    { return priVarsSwitchedInLastIteration_; }

private:
    //! the class handling the primary variable switch
    std::unique_ptr<PrimaryVariableSwitch> priVarSwitch_;
    //! if we switched primary variables in the last iteration
    bool priVarsSwitchedInLastIteration_ = false;
};

/*!
 * \ingroup Nonlinear
 * \brief An empty adapter for the Newton for models without primary variable switch
 */
template <class Variables>
class PrimaryVariableSwitchAdapter<Variables, false>
{
public:
    PrimaryVariableSwitchAdapter(const std::string& paramGroup = "") {}

    template<class SolutionVector>
    void initialize(SolutionVector&, Variables&) {}

    template<class SolutionVector>
    void invoke(SolutionVector&, Variables&) {}

    bool switched() const { return false; }
};

} // end namespace Dumux

#endif