GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/examples/embedded_network_1d3d/main.cc
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 127 128 99.2%
Functions: 1 4 25.0%
Branches: 251 578 43.4%

Line Branch Exec Source
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 //
4 // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 // # The main file (`main.cc`)
8 //
9 // This file contains the `main` function and implements the main program
10 // flow. We initialize the simulation framework, initialize parameters,
11 // create the grids (using parameters from the configuration file `params.input`),
12 // create vector to store the primary and secondary variables, construct an
13 // assembler that can assembly the the residual (discrete equations) and
14 // the system matrix (Jacobian of the residual), and create a linear solver
15 // that solves the linear system arising in each time step. The time loop
16 // implements a simple time stepping scheme with constant time step size.
17 //
18 // [[content]]
19 //
20 // ### Included header files
21 // [[details]] includes
22 // [[codeblock]]
23 #include <config.h>
24
25 #include <vector>
26 #include <numeric>
27
28 #include <dune/common/timer.hh>
29 #include <dune/common/fvector.hh>
30
31 #include <dumux/common/properties.hh>
32 #include <dumux/common/parameters.hh>
33 #include <dumux/common/initialize.hh>
34
35 #include <dumux/io/vtkoutputmodule.hh>
36 #include <dumux/io/container.hh>
37 #include <dumux/io/format.hh>
38 #include <dumux/io/grid/gridmanager_yasp.hh>
39 #include <dumux/io/grid/gridmanager_foam.hh>
40
41 #include <dumux/multidomain/traits.hh>
42 #include <dumux/multidomain/fvassembler.hh>
43 #include <dumux/multidomain/newtonsolver.hh>
44
45 #include "bloodflow.hh"
46 #include "solver.hh"
47 #include "properties.hh"
48 // [[/codeblock]]
49 // [[/details]]
50 //
51 // ## The main function
52 // We will now discuss the main program flow implemented within the `main` function.
53 // At the beginning of each program using Dune, an instance of `Dune::MPIHelper` has to
54 // be created. Moreover, we parse the run-time arguments from the command line and the
55 // input file:
56 1 int main(int argc, char** argv) {
57 // enable all symbols of the Dumux namespace without having to prefix with ``Dumux::``
58 1 using namespace Dumux;
59 //
60 // ### initialization and parameter setup
61 // [[codeblock]]
62 // initialize (e.g. multi-threading backend)
63 1 initialize(argc, argv);
64
65 // parse command line arguments and input file
66
9/24
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
6 Parameters::init(argc, argv);
67 // [[/codeblock]]
68
69 // Define the sub problem type tags (collection of model properties)
70 1 using Model3D = Properties::TTag::TissueTransportModel;
71 1 using Model1D = Properties::TTag::NetworkTransportModel;
72
73 // Start the timer (to measure code execution time)
74 1 Dune::Timer timer;
75
76 // ### Grid setup
77 // [[codeblock]]
78 // Create grids (see input file groups "[Tissue.Grid]" and "[Network.Grid]")
79 // See properties.hh for the types of Grid
80 1 using Grid3D = GetPropType<Model3D, Properties::Grid>;
81 2 GridManager<Grid3D> gridManager3D;
82
5/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
2 gridManager3D.init("Tissue");
83
84 1 using Grid1D = GetPropType<Model1D, Properties::Grid>;
85
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 GridManager<Grid1D> gridManager1D;
86
5/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
2 gridManager1D.init("Network");
87
88 // get data from grid file like vessel radii and fluxes in the network
89
1/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2 auto gridData1D = gridManager1D.getGridData();
90
91 // we compute on the leaf grid view (the refined elements)
92
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 const auto& gridView3D = gridManager3D.grid().leafGridView();
93
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 const auto& gridView1D = gridManager1D.grid().leafGridView();
94
95 // create the finite volume grid geometries on top of the grid
96 // this enables us to iterate over (sub-)control-volumes and faces
97 1 using GridGeometry3D = GetPropType<Model3D, Properties::GridGeometry>;
98 1 using GridGeometry1D = GetPropType<Model1D, Properties::GridGeometry>;
99
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 auto gridGeometry3D = std::make_shared<GridGeometry3D>(gridView3D);
100
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 auto gridGeometry1D = std::make_shared<GridGeometry1D>(gridView1D);
101
102 // print info about the grid setup time
103 1 const auto gridSetupTime = timer.elapsed();
104
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
3 std::cout << "Setting up grid geometry took " << gridSetupTime << " seconds." << std::endl;
105 // [[/codeblock]]
106 //
107 // ### Coupling manager
108 //
109 // [[codeblock]]
110 // the mixed dimension type traits (create coupled model properties)
111 1 using CoupledModelTraits = MultiDomainTraits<Model3D, Model1D>;
112 1 constexpr auto domain3D = CoupledModelTraits::template SubDomain<0>::Index();
113 1 constexpr auto domain1D = CoupledModelTraits::template SubDomain<1>::Index();
114
115 // the coupling manager (handles data mapping between 1D and 3D domains)
116 1 using CouplingManager = Properties::CouplingTransport;
117
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 auto couplingManager = std::make_shared<CouplingManager>(gridGeometry3D, gridGeometry1D);
118
119 // the problem (initial and boundary conditions, source and coupling terms)
120 // these class are defined in `problem.hh` and then defines as "properties" in `properties.hh`
121 // the constructor is whatever is defined as a constructor in `problem.hh`, so the user is
122 // free to change this to whatever works. Here we added the argument `gridData1D` to hand
123 // the grid parameters read from the grid file to the problem class instance
124 1 using TransportProblem3D = GetPropType<Model3D, Properties::Problem>;
125 1 using TransportProblem1D = GetPropType<Model1D, Properties::Problem>;
126
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 auto transportProblem3D = std::make_shared<TransportProblem3D>(gridGeometry3D, couplingManager, "Tissue");
127
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 auto transportProblem1D = std::make_shared<TransportProblem1D>(gridGeometry1D, couplingManager, gridData1D, "Network");
128
129 // solve blood flow problem to obtain volume fluxes
130
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 auto bloodVolumeFluxes = computeBloodVolumeFluxes(gridGeometry1D, gridData1D);
131
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 transportProblem1D->spatialParams().setVolumeFluxes(bloodVolumeFluxes);
132 // [[/codeblock]]
133 //
134 // ### Solution vector
135 //
136 // [[codeblock]]
137 // the solution vector (here: mole fractions of the transported solute)
138
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 CoupledModelTraits::SolutionVector sol;
139
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 transportProblem3D->applyInitialSolution(sol[domain3D]);
140
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 transportProblem1D->applyInitialSolution(sol[domain1D]);
141
142 // this is a time-dependent problem, so we create a second solution vector that
143 // represents the solution at the previous time level
144
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 auto oldSol = sol;
145 // [[/codeblock]]
146 //
147 // ### Coupling manager
148 //
149 // [[codeblock]]
150 // initialize coupling
151
3/10
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
3 couplingManager->init(transportProblem3D, transportProblem1D, sol);
152 // in the case of 1D-3D the coupling needs point sources to be enabled for both sub-problems
153 // each point sources constitutes an integration point for the coupling operator
154
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 transportProblem3D->computePointSourceMap();
155
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 transportProblem1D->computePointSourceMap();
156
157 // the grid variables (secondary variables and caching of computed variables)
158 // for instance the effective diffusion coefficient that is computed from
159 // the free diffusion coefficient (fluid system) and the porosity and tortuosity (spatial parameter)
160 1 using GridVariables3D = GetPropType<Model3D, Properties::GridVariables>;
161
1/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2 auto gridVariables3D = std::make_shared<GridVariables3D>(transportProblem3D, gridGeometry3D);
162
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 gridVariables3D->init(sol[domain3D]);
163 1 using GridVariables1D = GetPropType<Model1D, Properties::GridVariables>;
164
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 auto gridVariables1D = std::make_shared<GridVariables1D>(transportProblem1D, gridGeometry1D);
165
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 gridVariables1D->init(sol[domain1D]);
166 // [[/codeblock]]
167 //
168 // ### VTK output
169 //
170 // [[codeblock]]
171 // initialize the VTK output
172 1 using Solution3D = std::decay_t<decltype(sol[domain3D])>;
173
9/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
4 VtkOutputModule<GridVariables3D, Solution3D> vtkWriter3D(*gridVariables3D, sol[domain3D], transportProblem3D->name());
174
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 GetPropType<Model3D, Properties::IOFields>::initOutputModule(vtkWriter3D);
175 1 using Solution1D = std::decay_t<decltype(sol[domain1D])>;
176
8/16
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
3 VtkOutputModule<GridVariables1D, Solution1D> vtkWriter1D(*gridVariables1D, sol[domain1D], transportProblem1D->name());
177
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 GetPropType<Model1D, Properties::IOFields>::initOutputModule(vtkWriter1D);
178
179 // we compute with mole fraction as primary variables because they are continuous across material interfaces
180 // for the output, we compute fluid concentration c = rho*x and total/voxel concentration ct = porosity*c
181 // mmol/l is equivalent to mol/m^3, the balance equation is in mol/s (change of tracer amount per time)
182
7/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
4 vtkWriter3D.addVolumeVariable( [](const auto& v){ return v.molarDensity()*v.moleFraction(0,0); }, "c fluid (mmol/l)");
183
7/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
4 vtkWriter3D.addVolumeVariable( [](const auto& v){ return v.molarDensity()*v.moleFraction(0,0)*v.porosity(); }, "c total (mmol/l)");
184
185 // for the network domain we want to output the vessel lumen radius for visualization
186 // and the outer vessel radius (where we couple with the tissue domain)
187
8/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
3 vtkWriter1D.addField(transportProblem1D->spatialParams().getVesselRadii(), "vessel radius (m)");
188
8/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
3 vtkWriter1D.addField(transportProblem1D->spatialParams().getOuterRadii(), "outer radius (m)");
189
8/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
2 vtkWriter1D.addField(transportProblem1D->spatialParams().getVesselSegmentLengths(), "length");
190
7/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
4 vtkWriter1D.addVolumeVariable( [](const auto& v){ return v.molarDensity()*v.moleFraction(0,0); }, "c fluid (mmol/l)");
191
192 // write out initial solution
193
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 vtkWriter3D.write(0.0, Dune::VTK::OutputType::appendedraw);
194
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 vtkWriter1D.write(0.0, Dune::VTK::OutputType::appendedraw);
195 // [[/codeblock]]
196 //
197 // ### Time loop configuration, assembler and linear solver
198 //
199 // [[codeblock]]
200 ////////////////////////////////////////////////////////////
201 // Time loop with assembler and linear solver
202 ////////////////////////////////////////////////////////////
203
204 // get some time loop parameters and make time loop
205
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const auto dt = getParam<double>("TimeLoop.DtInitial");
206
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const auto tEnd = getParam<double>("TimeLoop.TEnd");
207
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 auto timeLoop = std::make_shared<CheckPointTimeLoop<double>>(0.0, dt, tEnd);
208
209 // the assembler with time loop for a coupled transient problem
210 1 using Assembler = MultiDomainFVAssembler<CoupledModelTraits, CouplingManager, DiffMethod::numeric>;
211 1 auto assembler = std::make_shared<Assembler>(
212 1 std::make_tuple(transportProblem3D, transportProblem1D),
213 2 std::make_tuple(gridGeometry3D, gridGeometry1D),
214
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 std::make_tuple(gridVariables3D, gridVariables1D),
215 couplingManager, timeLoop, oldSol
216
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2 );
217
218 // construct the linear solver (see solver.hh)
219 1 using LinearSolver = Example::BlockDiagILU0BiCGSTABSolver<typename Assembler::JacobianMatrix, typename Assembler::ResidualType>;
220
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 auto linearSolver = std::make_shared<LinearSolver>();
221 // [[/codeblock]]
222 //
223 // ### Output of the tracer concentration
224 //
225 // [[codeblock]]
226 // output time and tracer amount in tissue
227
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 const auto filePrefix = getParam<std::string>("Problem.Name");
228
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
2 std::vector<Dune::FieldVector<double, 2>> tracerAmounts;
229
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 tracerAmounts.reserve(std::size_t(std::ceil(tEnd/dt)));
230
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
4 const auto initTracerAmount = transportProblem3D->computeTracerAmount(sol[domain3D], *gridVariables3D);
231
3/8
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
1 std::cout << Fmt::format("Initial amount of tracer in tissue: {:.2e}\n", initTracerAmount);
232
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 tracerAmounts.push_back(Dune::FieldVector<double, 2>{ 0.0, initTracerAmount });
233 // [[/codeblock]]
234 //
235 // ### Time loop
236 //
237 // [[codeblock]]
238 // start the time loop
239
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 timeLoop->start();
240
4/6
✓ Branch 1 taken 101 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 101 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 100 times.
✓ Branch 7 taken 1 times.
202 while (!timeLoop->finished())
241 {
242 // construct some timers to measure the execution time of the time integration steps
243 100 Dune::Timer assembleTimer(false), solveTimer(false), updateTimer(false), outputTimer(false);
244
1/2
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
200 std::cout << "\nAssemble linear system " << std::endl;
245
246 // assemble stiffness matrix and/or residual
247 // we only assemble the Jacobian (stiffness matrix for a linear problem) once
248 // in the subsequent time steps only the right-hand side (residual) changes
249
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 assembleTimer.start();
250
2/4
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
200 couplingManager->updateSolution(sol);
251
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 99 times.
200 if (timeLoop->timeStepIndex() == 0)
252
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 assembler->assembleJacobianAndResidual(sol);
253 else
254
3/6
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 99 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 99 times.
✗ Branch 8 not taken.
297 assembler->assembleResidual(sol);
255 100 assembleTimer.stop();
256
257
5/14
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 100 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 100 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
400 std::cout << "Solve linear system (" << linearSolver->name() << ")" << std::endl;
258
259 // solve linear system
260 // the first time we tell the solver about the Jacobian
261 // then we solve with updated right-hand sides (residual)
262
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 solveTimer.start();
263
1/2
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
200 auto deltaSol = sol;
264
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 99 times.
200 if (timeLoop->timeStepIndex() == 0)
265
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
4 linearSolver->setup(assembler->jacobian());
266
267
4/8
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 100 times.
✗ Branch 11 not taken.
400 const bool converged = linearSolver->solve(deltaSol, assembler->residual());
268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!converged)
269 DUNE_THROW(Dune::MathError, "Linear solver did not converge!");
270 100 solveTimer.stop();
271
272 // update solution and primary and secondary variables
273 // and tell the coupling manager about the new solution
274
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 updateTimer.start();
275 100 sol -= deltaSol;
276
2/4
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
200 couplingManager->updateSolution(sol);
277
3/6
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
300 gridVariables3D->update(sol[domain3D]);
278
3/6
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
300 gridVariables1D->update(sol[domain1D]);
279
280 // make the new solution the old solution
281
1/2
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
100 oldSol = sol;
282
2/4
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
200 gridVariables3D->advanceTimeStep();
283
2/4
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
200 gridVariables1D->advanceTimeStep();
284 100 updateTimer.stop();
285
286 // advance to the time loop to the next step
287
2/4
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
200 timeLoop->advanceTimeStep();
288
289 // write vtk output
290
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 outputTimer.start();
291
3/6
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
300 vtkWriter3D.write(timeLoop->time(), Dune::VTK::OutputType::appendedraw);
292
3/6
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
300 vtkWriter1D.write(timeLoop->time(), Dune::VTK::OutputType::appendedraw);
293
294 // Compute total tracer mass in domain and write to file
295
4/8
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 100 times.
✗ Branch 11 not taken.
400 const auto tracerAmount = transportProblem3D->computeTracerAmount(sol[domain3D], *gridVariables3D);
296
3/8
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
100 std::cout << Fmt::format("Current amount of tracer in ECS: {:.2e}\n", tracerAmount);
297
4/8
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 100 times.
✗ Branch 11 not taken.
400 tracerAmounts.push_back(Dune::FieldVector<double, 2>{ timeLoop->time(), tracerAmount });
298
2/6
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
200 Dumux::writeContainerToFile(tracerAmounts, Fmt::format("{}_tracer_amounts.dat", filePrefix));
299 100 outputTimer.stop();
300
301 // output timings
302 100 const auto elapsedTot = assembleTimer.elapsed() + solveTimer.elapsed() + updateTimer.elapsed() + outputTimer.elapsed();
303 100 std::cout << "Assemble/solve/update/output time: "
304
2/4
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
200 << assembleTimer.elapsed() << "(" << 100*assembleTimer.elapsed()/elapsedTot << "%)/"
305
2/4
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
200 << solveTimer.elapsed() << "(" << 100*solveTimer.elapsed()/elapsedTot << "%)/"
306
2/4
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
200 << updateTimer.elapsed() << "(" << 100*updateTimer.elapsed()/elapsedTot << "%)/"
307
2/4
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
200 << outputTimer.elapsed() << "(" << 100*outputTimer.elapsed()/elapsedTot << "%)"
308
1/2
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
200 << "\n";
309
310 // report statistics of this time step
311
2/4
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
200 timeLoop->reportTimeStep();
312
313 // use same time step size in next time step
314 // this function can be used to implement time step adaptivity
315
2/4
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
200 timeLoop->setTimeStepSize(dt);
316 }
317 // [[/codeblock]]
318 //
319 // ### Finalize
320 //
321 // [[codeblock]]
322 // end the time loop and produce report
323
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
2 timeLoop->finalize(gridView3D.comm());
324
325 // output (manual) timings
326
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 std::cout << "Transport computation took " << timer.elapsed() - gridSetupTime << " seconds." << std::endl;
327
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 std::cout << "Simulation took " << timer.elapsed() << " seconds." << std::endl;
328
329 // Print used/unused parameters at the end (good for debugging)
330
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 Parameters::print();
331
332
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return 0;
333 }
334 // [[/codeblock]]
335 // [[/content]]
336