main.cc 9.02 KB
Newer Older
Dennis Gläser's avatar
Dennis Gläser committed
1
2
3
4
5
6
7
// -*- 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    *
8
 *   the Free Software Foundation, either version 3 of the License, or       *
Dennis Gläser's avatar
Dennis Gläser committed
9
10
11
12
13
14
15
16
17
18
19
20
 *   (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
21
22
 * \ingroup GeomechanicsTests
 * \brief Test for the poro-elastic model.
Dennis Gläser's avatar
Dennis Gläser committed
23
24
25
26
27
28
29
30
31
32
33
 */
#include <config.h>

#include <ctime>
#include <iostream>

#include <dune/common/parallel/mpihelper.hh>
#include <dune/common/timer.hh>
#include <dune/common/fvector.hh>
#include <dune/grid/io/file/vtk.hh>

34
#include "properties.hh"
Dennis Gläser's avatar
Dennis Gläser committed
35
36
37
38
39
40

#include <dumux/common/properties.hh>
#include <dumux/common/parameters.hh>
#include <dumux/common/dumuxmessage.hh>

#include <dumux/linear/amgbackend.hh>
41
#include <dumux/linear/linearsolvertraits.hh>
Dennis Gläser's avatar
Dennis Gläser committed
42
43
44
45
46
#include <dumux/nonlinear/newtonsolver.hh>

#include <dumux/assembly/fvassembler.hh>
#include <dumux/assembly/diffmethod.hh>

47
#include <dumux/discretization/method.hh>
Dennis Gläser's avatar
Dennis Gläser committed
48
49
#include <dumux/discretization/elementsolution.hh>
#include <dumux/io/vtkoutputmodule.hh>
50
#include <dumux/io/grid/gridmanager.hh>
Dennis Gläser's avatar
Dennis Gläser committed
51
52
53
54
55
56
57
58
59
60

// function to evaluate the element stresses
template< class StressType,
          class Problem,
          class GridVariables,
          class SolutionVector,
          class SigmaStorage >
void assembleElementStresses(SigmaStorage& sigmaStorage,
                             SigmaStorage& effSigmaStorage,
                             const Problem& problem,
61
                             const typename GridVariables::GridGeometry& gridGeometry,
Dennis Gläser's avatar
Dennis Gläser committed
62
63
64
                             const GridVariables& gridVariables,
                             const SolutionVector& x)
{
65
    for (const auto& element : elements(gridGeometry.gridView()))
Dennis Gläser's avatar
Dennis Gläser committed
66
    {
67
        auto fvGeometry = localView(gridGeometry);
Dennis Gläser's avatar
Dennis Gläser committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
        auto elemVolVars = localView(gridVariables.curGridVolVars());

        fvGeometry.bind(element);
        elemVolVars.bind(element, fvGeometry, x);

        // evaluate flux variables cache at cell center
        using FluxVarsCache = typename GridVariables::GridFluxVariablesCache::FluxVariablesCache;
        FluxVarsCache fluxVarsCache;
        fluxVarsCache.update(problem, element, fvGeometry, elemVolVars, element.geometry().center());

        // get lame parameters, the pressure and compute stress tensor
        const auto sigma = StressType::stressTensor(problem, element, fvGeometry, elemVolVars, fluxVarsCache);
        const auto effSigma = StressType::effectiveStressTensor(problem, element, fvGeometry, elemVolVars, fluxVarsCache);

        // pass values into storage container
83
84
        using GridGeometry = typename GridVariables::GridGeometry;
        for (int dir = 0; dir < GridGeometry::GridView::dimension; ++dir)
Dennis Gläser's avatar
Dennis Gläser committed
85
        {
86
            const auto eIdx = gridGeometry.elementMapper().index(element);
Dennis Gläser's avatar
Dennis Gläser committed
87
88
89
90
91
92
93
            sigmaStorage[dir][eIdx] = sigma[dir];
            effSigmaStorage[dir][eIdx] = effSigma[dir];
        }
    }
}

// main function
94
int main(int argc, char** argv)
Dennis Gläser's avatar
Dennis Gläser committed
95
96
97
98
{
    using namespace Dumux;

    // define the type tag for this problem
99
    using TypeTag = Properties::TTag::TestPoroElastic;
Dennis Gläser's avatar
Dennis Gläser committed
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

    // stop time for the entire computation
    Dune::Timer timer;

    // initialize MPI, finalize is done automatically on exit
    const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv);

    // print dumux start message
    if (mpiHelper.rank() == 0)
        DumuxMessage::print(/*firstCall=*/true);

    // parse command line arguments and input file
    Parameters::init(argc, argv);

    // try to create a grid (from the given grid file or the input file)
115
    GridManager<GetPropType<TypeTag, Properties::Grid>> gridManager;
116
    gridManager.init();
Dennis Gläser's avatar
Dennis Gläser committed
117
118
119
120
121
122

    ////////////////////////////////////////////////////////////
    // run non-linear problem on this grid
    ////////////////////////////////////////////////////////////

    // we compute on the leaf grid view
123
    const auto& leafGridView = gridManager.grid().leafGridView();
Dennis Gläser's avatar
Dennis Gläser committed
124
125

    // create the finite volume grid geometry
126
    using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
127
128
    auto gridGeometry = std::make_shared<GridGeometry>(leafGridView);
    gridGeometry->update();
Dennis Gläser's avatar
Dennis Gläser committed
129
130

    // the problem (initial and boundary conditions)
131
    using Problem = GetPropType<TypeTag, Properties::Problem>;
132
    auto problem = std::make_shared<Problem>(gridGeometry);
Dennis Gläser's avatar
Dennis Gläser committed
133
134

    // the solution vector
135
    using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
136
    SolutionVector x(gridGeometry->numDofs());
Dennis Gläser's avatar
Dennis Gläser committed
137
138
139
    problem->applyInitialSolution(x);

    // the grid variables
140
    using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
141
    auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
Dennis Gläser's avatar
Dennis Gläser committed
142
143
144
    gridVariables->init(x);

    // intialize the vtk output module and output fields
145
    using IOFields = GetPropType<TypeTag, Properties::IOFields>;
Timo Koch's avatar
Timo Koch committed
146
147
    using VtkOutputModule = Dumux::VtkOutputModule<GridVariables, SolutionVector>;
    VtkOutputModule vtkWriter(*gridVariables, x, problem->name());
148
    IOFields::initOutputModule(vtkWriter);
Dennis Gläser's avatar
Dennis Gläser committed
149

150
    // also, add exact solution to the output
151
    SolutionVector xExact(gridGeometry->numDofs());
Dennis Gläser's avatar
Dennis Gläser committed
152
    for (const auto& v : vertices(leafGridView))
153
        xExact[ gridGeometry->vertexMapper().index(v) ] = problem->exactSolution(v.geometry().center());
Dennis Gläser's avatar
Dennis Gläser committed
154
155
156
    vtkWriter.addField(xExact, "u_exact");

    // Furthermore, write out element stress tensors
157
158
    static constexpr int dim = GridGeometry::GridView::dimension;
    static constexpr int dimWorld = GridGeometry::GridView::dimensionworld;
159
    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
Dennis Gläser's avatar
Dennis Gläser committed
160
161
162
163
164
165
    using ForceVector = Dune::FieldVector< Scalar, dimWorld >;

    // containers to store sigma/effective sigma
    std::array< std::vector<ForceVector>, dim > sigmaStorage;
    std::array< std::vector<ForceVector>, dim > effSigmaStorage;

166
    const auto numCells = gridGeometry->gridView().size(0);
Dennis Gläser's avatar
Dennis Gläser committed
167
168
169
170
171
172
173
174
175
176
    std::for_each(sigmaStorage.begin(), sigmaStorage.end(), [numCells] (auto& sigma) { sigma.resize(numCells); });
    std::for_each(effSigmaStorage.begin(), effSigmaStorage.end(), [numCells] (auto& effSigma) { effSigma.resize(numCells); });

    for (int dir = 0; dir < dim; ++dir)
    {
        vtkWriter.addField(sigmaStorage[dir], "sigma_" + std::to_string(dir), VtkOutputModule::FieldType::element);
        vtkWriter.addField(effSigmaStorage[dir], "effSigma_" + std::to_string(dir), VtkOutputModule::FieldType::element);
    }

    // use convenience function to compute stresses
177
    using StressType = GetPropType<TypeTag, Properties::StressType>;
178
    assembleElementStresses<StressType>(sigmaStorage, effSigmaStorage, *problem, *gridGeometry, *gridVariables, x);
Dennis Gläser's avatar
Dennis Gläser committed
179
180
181
182
183
184

    // write initial solution
    vtkWriter.write(0.0);

    // the assembler with time loop for instationary problem
    using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
185
    auto assembler = std::make_shared<Assembler>(problem, gridGeometry, gridVariables);
Dennis Gläser's avatar
Dennis Gläser committed
186
187

    // the linear solver
188
    using LinearSolver = AMGBiCGSTABBackend<LinearSolverTraits<GridGeometry>>;
189
    auto linearSolver = std::make_shared<LinearSolver>(leafGridView, gridGeometry->dofMapper());
Dennis Gläser's avatar
Dennis Gläser committed
190
191
192
193
194
195
196
197
198
199
200
201

    // the non-linear solver
    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
    NewtonSolver nonLinearSolver(assembler, linearSolver);

    // linearize & solve
    nonLinearSolver.solve(x);

    // the grid variables need to be up to date for subsequent output
    gridVariables->update(x);

    // write vtk output
202
    assembleElementStresses<StressType>(sigmaStorage, effSigmaStorage, *problem, *gridGeometry, *gridVariables, x);
Dennis Gläser's avatar
Dennis Gläser committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    vtkWriter.write(1.0);

    // print time and say goodbye
    const auto& comm = Dune::MPIHelper::getCollectiveCommunication();
    if (mpiHelper.rank() == 0)
        std::cout << "Simulation took " << timer.elapsed() << " seconds on "
                  << comm.size() << " processes.\n"
                  << "The cumulative CPU time was " << timer.elapsed()*comm.size() << " seconds.\n";

    // print parameters
    if (mpiHelper.rank() == 0)
        Parameters::print();

    return 0;
} // end main