GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/examples/embedded_network_1d3d/bloodflow.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 104 141 73.8%
Functions: 9 19 47.4%
Branches: 121 348 34.8%

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
8 #ifndef DUMUX_EXAMPLE_BLOODFLOW_SOLVER_HH
9 #define DUMUX_EXAMPLE_BLOODFLOW_SOLVER_HH
10
11 #include <memory>
12
13 #include <dune/foamgrid/foamgrid.hh>
14
15 #include <dumux/common/exceptions.hh>
16 #include <dumux/common/parameters.hh>
17 #include <dumux/common/properties.hh>
18 #include <dumux/common/numeqvector.hh>
19 #include <dumux/common/reorderingdofmapper.hh>
20
21 #include <dumux/io/format.hh>
22
23 #include <dumux/discretization/cctpfa.hh>
24
25 #include <dumux/porousmediumflow/problem.hh>
26 #include <dumux/porousmediumflow/1p/model.hh>
27 #include <dumux/porousmediumflow/1p/incompressiblelocalresidual.hh>
28 #include <dumux/porousmediumflow/fvspatialparams1p.hh>
29
30 #include <dumux/material/components/constant.hh>
31 #include <dumux/material/fluidsystems/1pliquid.hh>
32
33 #include <dumux/linear/istlsolvers.hh>
34 #include <dumux/linear/linearsolvertraits.hh>
35 #include <dumux/linear/linearalgebratraits.hh>
36 #include <dumux/assembly/fvassembler.hh>
37 #include <dumux/nonlinear/newtonsolver.hh>
38
39 namespace Dumux::BloodFlowSolver {
40
41 template<class TypeTag>
42 class BloodFlowProblem : public PorousMediumFlowProblem<TypeTag>
43 {
44 using ParentType = PorousMediumFlowProblem<TypeTag>;
45
46 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
47 using PointSource = GetPropType<TypeTag, Properties::PointSource>;
48 using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
49 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
50 using BoundaryTypes = Dumux::BoundaryTypes<PrimaryVariables::size()>;
51 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
52 using GridView = typename GridGeometry::GridView;
53 using FVElementGeometry = typename GridGeometry::LocalView;
54 using SubControlVolume = typename GridGeometry::SubControlVolume;
55 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
56 using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
57 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
58 using Element = typename GridView::template Codim<0>::Entity;
59 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
60 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
61 static constexpr int dim = GridView::dimension;
62
63 public:
64 template<class GridData>
65 1 BloodFlowProblem(std::shared_ptr<const GridGeometry> gridGeometry,
66 std::shared_ptr<GridData> gridData)
67
8/22
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✓ Branch 15 taken 1 times.
✗ Branch 16 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.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
3 : ParentType(gridGeometry)
68 {
69 // read spatial parameters
70
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 this->spatialParams().readGridParams(*gridData);
71
72 // mapping from element index to boundaryFlag
73
1/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 referencePressure_ = getParam<Scalar>("Problem.ReferencePressure", 0.0);
74
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 setBoundaryDomainMarker_(*gridData);
75 1 }
76
77 PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
78 3470 { return { 0.0 }; }
79
80 /////////////////////////////////////////////////////////////////////////////////
81 /////// CC Tpfa /////////////////////////////////////////////////////////////////
82 BoundaryTypes boundaryTypes(const Element& element, const SubControlVolumeFace& scvf) const
83 {
84
3/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 252 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 252 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 504 times.
✗ Branch 9 not taken.
1008 BoundaryTypes bcTypes;
85
3/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 252 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 252 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 504 times.
✗ Branch 9 not taken.
1008 bcTypes.setAllDirichlet();
86 return bcTypes;
87 }
88
89 PrimaryVariables dirichlet(const Element& element, const SubControlVolumeFace& scvf) const
90 {
91
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
504 PrimaryVariables values(0.0);
92
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
504 values[Indices::pressureIdx] = this->bloodPressureBoundaryScvf(scvf.index());
93 return values;
94 }
95
96 //! blood pressure for boundary sub control volume faces
97 504 Scalar bloodPressureBoundaryScvf(std::size_t scvfIndex) const
98 {
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 const auto p = bloodPressureBoundary_[scvfIndex];
100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 if (std::isnan(p))
101 DUNE_THROW(Dune::InvalidStateException, "Invalid scvf index for boundary pressure!");
102 504 return p;
103 }
104
105 // compute volume fluxes as input for the transport model
106 1 std::vector<Scalar> computeVolumeFluxes(const SolutionVector& sol, const GridVariables& gridVars)
107 {
108 1 const auto& gg = this->gridGeometry();
109 3 std::vector<Scalar> volumeFlux(gg.numScvf(), 0.0);
110
111 using FluxVariables = GetPropType<TypeTag, Properties::FluxVariables>;
112 13410 auto upwindTerm = [](const auto& volVars) { return volVars.mobility(Indices::conti0EqIdx); };
113
114 1 auto fvGeometry = localView(gg);
115 3 auto elemVolVars = localView(gridVars.curGridVolVars());
116 2 auto elemFluxVars = localView(gridVars.gridFluxVarsCache());
117
6/6
✓ Branch 2 taken 1735 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1735 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1734 times.
✓ Branch 7 taken 1 times.
1737 for (const auto& element : elements(gg.gridView()))
118 {
119
2/2
✓ Branch 0 taken 1734 times.
✓ Branch 1 taken 1 times.
1735 fvGeometry.bind(element);
120
1/2
✓ Branch 1 taken 1735 times.
✗ Branch 2 not taken.
1735 elemVolVars.bind(element, fvGeometry, sol);
121 1735 elemFluxVars.bind(element, fvGeometry, elemVolVars);
122
123
6/6
✓ Branch 0 taken 3470 times.
✓ Branch 1 taken 1735 times.
✓ Branch 2 taken 3470 times.
✓ Branch 3 taken 1735 times.
✓ Branch 4 taken 3344 times.
✓ Branch 5 taken 126 times.
6940 for (const auto& scvf : scvfs(fvGeometry))
124 {
125 3470 const auto scvfIdx = scvf.index();
126
127
2/2
✓ Branch 0 taken 3344 times.
✓ Branch 1 taken 126 times.
3470 if (!scvf.boundary())
128 {
129
1/2
✓ Branch 1 taken 3344 times.
✗ Branch 2 not taken.
3344 FluxVariables fluxVars;
130
1/2
✓ Branch 1 taken 3344 times.
✗ Branch 2 not taken.
3344 fluxVars.init(*this, element, fvGeometry, elemVolVars, scvf, elemFluxVars);
131
1/2
✓ Branch 1 taken 3344 times.
✗ Branch 2 not taken.
3344 volumeFlux[scvfIdx] = fluxVars.advectiveFlux(Indices::conti0EqIdx, upwindTerm);
132 }
133 else
134 {
135
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 const auto bcTypes = boundaryTypes(element, scvf);
136
2/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
252 if (bcTypes.hasOnlyDirichlet()) // Dirichlet
137 {
138
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 FluxVariables fluxVars;
139
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 fluxVars.init(*this, element, fvGeometry, elemVolVars, scvf, elemFluxVars);
140
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 volumeFlux[scvfIdx] = fluxVars.advectiveFlux(Indices::conti0EqIdx, upwindTerm);
141 }
142
143 else // Neumann
144 {
145 volumeFlux[scvfIdx] = this->neumann(element, fvGeometry, elemVolVars, 0.0, scvf)[Indices::pressureIdx]
146 * scvf.area() * elemVolVars[0].extrusionFactor()
147 / elemVolVars[0].density(); // volume flux from mass flux
148 }
149 }
150 }
151 }
152
153 1 return volumeFlux;
154 }
155
156 private:
157 template<class GridData>
158 1 void setBoundaryDomainMarker_(const GridData& gridData)
159 {
160 1 const auto& gg = this->gridGeometry();
161
162 // this is a bit difficult as we need to map from vertex to scvf.
163 // maybe an scvf specialization for 1d could help containing the vertex index?
164 2 bloodPressureBoundary_.resize(gg.numScvf(), std::numeric_limits<Scalar>::quiet_NaN());
165 2 bloodPressureVertex_.resize(gg.gridView().size(GridView::dimension), std::numeric_limits<Scalar>::quiet_NaN());
166 1 auto fvGeometry = localView(gg);
167 1 std::size_t count = 0;
168
6/6
✓ Branch 2 taken 1735 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1735 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1734 times.
✓ Branch 7 taken 1 times.
3472 for (const auto& element : elements(gg.gridView()))
169 {
170
2/2
✓ Branch 0 taken 1734 times.
✓ Branch 1 taken 1 times.
1735 fvGeometry.bindElement(element);
171
4/6
✓ Branch 4 taken 5535 times.
✗ Branch 5 not taken.
✓ Branch 10 taken 126 times.
✓ Branch 11 taken 3674 times.
✓ Branch 13 taken 3800 times.
✗ Branch 14 not taken.
14336 for (const auto& intersection : intersections(gg.gridView(), element))
172 {
173
4/4
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 3674 times.
✓ Branch 2 taken 126 times.
✓ Branch 3 taken 3674 times.
7600 if (intersection.boundary())
174 {
175 // go up to the 0 level vertex
176 auto level0element = intersection.inside();
177
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 126 times.
252 while (level0element.hasFather())
178 level0element = level0element.father();
179
180 126 const auto scvfIdxGlobal = [&]()
181 {
182
3/6
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 126 times.
✗ Branch 5 not taken.
252 for (const auto& scvf : scvfs(fvGeometry))
183 {
184
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 if (scvf.boundary())
185
3/4
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 126 times.
✗ Branch 4 not taken.
294 if (Dune::FloatCmp::eq(scvf.unitOuterNormal() * intersection.centerUnitOuterNormal(), 1.0, eps_))
186 126 return scvf.index();
187 }
188
189 DUNE_THROW(Dune::InvalidStateException, "Boundary scvf not found!");
190
191
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 }();
192
193
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 126 times.
126 const auto vertex = level0element.template subEntity<dim>(intersection.indexInInside());
194
2/4
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 126 times.
✗ Branch 7 not taken.
126 bloodPressureVertex_[gg.vertexMapper().index(vertex)] = gridData.parameters(vertex)[0] - referencePressure_;
195
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 bloodPressureBoundary_[scvfIdxGlobal] = gridData.parameters(vertex)[0] - referencePressure_;
196 126 count++;
197 }
198 }
199 }
200
201
2/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
1 std::cout << Fmt::format("Extracted boundary data at {} boundary facets.\n", count);
202 1 }
203
204 static constexpr Scalar eps_ = 1e-7;
205 Scalar referencePressure_;
206 std::vector<Scalar> bloodPressureBoundary_; // blood pressure on boundary (Reichold/Schmid/Weber/Jenny)
207 std::vector<Scalar> bloodPressureVertex_; // blood pressure on boundary (Reichold/Schmid/Weber/Jenny)
208 };
209
210 } //end namespace Dumux
211
212 namespace Dumux::BloodFlowSolver {
213
214 template<class GridGeometry, class Scalar>
215 class BloodFlowSpatialParams
216 : public FVPorousMediumFlowSpatialParamsOneP<GridGeometry, Scalar, BloodFlowSpatialParams<GridGeometry, Scalar>>
217 {
218 using ThisType = BloodFlowSpatialParams<GridGeometry, Scalar>;
219 using ParentType = FVPorousMediumFlowSpatialParamsOneP<GridGeometry, Scalar, ThisType>;
220 using GridView = typename GridGeometry::GridView;
221 using FVElementGeometry = typename GridGeometry::LocalView;
222 using SubControlVolume = typename GridGeometry::SubControlVolume;
223 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
224 using Element = typename GridView::template Codim<0>::Entity;
225 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
226 static constexpr int dim = GridView::dimension;
227
228 public:
229 // export permeability type
230 using PermeabilityType = Scalar;
231
232 1 BloodFlowSpatialParams(std::shared_ptr<const GridGeometry> gridGeometry)
233
2/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 : ParentType(gridGeometry)
234 1 {}
235
236 template<class ElementSolution>
237 Scalar extrusionFactor(const Element& element,
238 const SubControlVolume& scv,
239 const ElementSolution& elemSol) const
240 {
241 const auto radius = this->radius(scv.elementIndex());
242 return M_PI*radius*radius;
243 }
244
245 Scalar porosityAtPos(const GlobalPosition& globalPos) const
246 { return 1.0; }
247
248 template<class ElementSolution>
249 PermeabilityType permeability(const Element& element,
250 const SubControlVolume& scv,
251 const ElementSolution& elemSol) const
252 {
253 return permeability_[scv.elementIndex()];
254 }
255
256 // Return the radius of the circular pipe
257 Scalar radius(std::size_t eIdxGlobal) const
258 { return radius_[eIdxGlobal];}
259
260 //! Get the radii for e.g. output
261 const std::vector<Scalar>& getRadii() const
262 { return radius_; }
263
264 //! Get the viscosity factors for e.g. output
265 const std::vector<Scalar>& getViscosityFactors() const
266 { return viscosityFactor_; }
267
268 //! Read params from dgf
269 template<class GridData>
270 1 void readGridParams(const GridData& gridData)
271 {
272 1 const auto& gg = this->gridGeometry();
273 2 auto numElements = gg.gridView().size(0);
274 1 radius_.resize(numElements);
275 1 permeability_.resize(numElements);
276 1 viscosityFactor_.resize(numElements);
277
278 // gridView is a leafGridView. Parameters are only set on level 0.
279 // elements have to inherit spatial parameters from their father.
280
4/4
✓ Branch 2 taken 1735 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1735 times.
✓ Branch 5 taken 1 times.
3472 for (const auto& element : elements(gg.gridView()))
281 {
282 1735 auto level0element = element;
283
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1735 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1735 times.
3470 while (level0element.hasFather())
284 level0element = level0element.father();
285
286 3470 auto eIdx = gg.elementMapper().index(element);
287 1735 const auto& params = gridData.parameters(level0element);
288 1735 radius_[eIdx] = params[0];
289
290 1735 constexpr Scalar dischargeHematocrit = 0.45;
291 1735 viscosityFactor_[eIdx] = etaVivo_(radius_[eIdx], dischargeHematocrit);
292 1735 constexpr Scalar gamma = 2; // quadratic velocity profile (Poiseuille flow)
293 3470 permeability_[eIdx] = radius_[eIdx]*radius_[eIdx]
294 1735 /(2.0*viscosityFactor_[eIdx]*(2.0+gamma));
295 }
296 1 }
297
298 Scalar temperatureAtPos(const GlobalPosition& globalPos) const
299 { return 273.15 + 37.0; } // Body temperature
300
301 private:
302 1735 Scalar etaVivo_(const Scalar radius, const Scalar dischargeHematocrit)
303 {
304 1735 const auto D = 2*radius*1e6*1.187; // times rat blood factor (55fl RBC), convert to µm
305 1735 const auto scaling = (D/(D - 1.1))*(D/(D - 1.1));
306 1735 const auto C = corrFactor_(D);
307 using std::exp; using std::pow;
308 1735 return scaling*(1.0 + scaling*(etaVivoH45_(D) - 1.0)*(pow(1.0 - dischargeHematocrit, C) - 1.0)/(pow(1.0 - 0.45, C) - 1.0));
309 }
310
311 Scalar etaVivoH45_(const Scalar D) // in µm
312 {
313 using std::exp; using std::pow;
314 return 6.0*exp(-0.085*D) - 2.44*exp(-0.06*pow(D, 0.645)) + 3.2;
315 }
316
317 Scalar corrFactor_(const Scalar D) // in µm
318 {
319 using std::exp; using std::pow;
320 const auto scaling = 1.0/(1.0 + 1e-11*pow(D, 12));
321 return (0.8 + exp(-0.075*D))*(scaling - 1.0) + scaling;
322 }
323
324 std::vector<Scalar> radius_;
325 std::vector<Scalar> permeability_;
326 std::vector<Scalar> viscosityFactor_;
327 };
328
329 } // end namespace Dumux
330
331 namespace Dumux::Properties {
332 namespace TTag { struct BloodFlowCCTpfa { using InheritsFrom = std::tuple<OneP, CCTpfaModel>; }; }
333
334 template<class TypeTag> struct EnableGridGeometryCache<TypeTag, TTag::BloodFlowCCTpfa> { static constexpr bool value = true; };
335 template<class TypeTag> struct EnableGridVolumeVariablesCache<TypeTag, TTag::BloodFlowCCTpfa> { static constexpr bool value = true; };
336 template<class TypeTag> struct EnableGridFluxVariablesCache<TypeTag, TTag::BloodFlowCCTpfa> { static constexpr bool value = true; };
337 template<class TypeTag> struct SolutionDependentAdvection<TypeTag, TTag::BloodFlowCCTpfa> { static constexpr bool value = false; };
338 template<class TypeTag> struct SolutionDependentMolecularDiffusion<TypeTag, TTag::BloodFlowCCTpfa> { static constexpr bool value = false; };
339 template<class TypeTag> struct SolutionDependentHeatConduction<TypeTag, TTag::BloodFlowCCTpfa> { static constexpr bool value = false; };
340
341 // Set the grid type
342 template<class TypeTag>
343 struct Grid<TypeTag, TTag::BloodFlowCCTpfa>
344 { using type = Dune::FoamGrid<1, 3>; };
345
346 // Set the problem property
347 template<class TypeTag>
348 struct Problem<TypeTag, TTag::BloodFlowCCTpfa>
349 { using type = BloodFlowSolver::BloodFlowProblem<TypeTag>; };
350
351 // Set the spatial parameters
352 template<class TypeTag>
353 struct SpatialParams<TypeTag, TTag::BloodFlowCCTpfa>
354 { using type = BloodFlowSolver::BloodFlowSpatialParams<GetPropType<TypeTag, Properties::GridGeometry>, double>; };
355
356 // the fluid system
357 template<class TypeTag>
358 struct FluidSystem<TypeTag, TTag::BloodFlowCCTpfa>
359 { using type = FluidSystems::OnePLiquid<double, Components::Constant<0, double> >; };
360
361 // Set the local residual
362 template<class TypeTag>
363 struct LocalResidual<TypeTag, TTag::BloodFlowCCTpfa>
364 { using type = OnePIncompressibleLocalResidual<TypeTag>; };
365
366 // if we have pt scotch use the reordering dof mapper to optimally sort the dofs (cc)
367 template<class TypeTag>
368 struct GridGeometry<TypeTag, TTag::BloodFlowCCTpfa>
369 {
370 private:
371 static constexpr bool enableCache = getPropValue<TypeTag, Properties::EnableGridGeometryCache>();
372 using GridView = typename GetPropType<TypeTag, Properties::Grid>::LeafGridView;
373 using ElementMapper = ReorderingDofMapper<GridView>;
374 using VertexMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
375 using MapperTraits = DefaultMapperTraits<GridView, ElementMapper, VertexMapper>;
376 public:
377 using type = CCTpfaFVGridGeometry<GridView, enableCache, CCTpfaDefaultGridGeometryTraits<GridView, MapperTraits>>;
378 };
379
380 } // end namespace Dumux::Properties
381
382 namespace Dumux {
383
384 template<class GridGeometry, class GridData>
385 1 std::vector<double> computeBloodVolumeFluxes(const GridGeometry& gridGeometry, const GridData& gridData)
386 {
387 // Define the sub problem type tags
388 using TypeTag = Properties::TTag::BloodFlowCCTpfa;
389
390 // start the timer
391 1 Dune::Timer timer;
392
393 ////////////////////////////////////////////////////////////
394 // Flow: prepare variables and problem
395 ////////////////////////////////////////////////////////////
396 using Problem = GetPropType<TypeTag, Properties::Problem>;
397
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 auto problem = std::make_shared<Problem>(gridGeometry, gridData);
398
399 // the solution vector
400 using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
401
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 SolutionVector sol;
402
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 problem->applyInitialSolution(sol);
403
404 // the grid variables
405 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
406
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 gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
407
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 gridVariables->init(sol);
408
409 // debug output
410 using VTKOutputModule = VtkOutputModule<GridVariables, SolutionVector>;
411
1/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 std::unique_ptr<VTKOutputModule> vtkWriter;
412
413
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 static const bool writeVTK = getParam<bool>("BloodFlow.WriteVTK", false);
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (writeVTK)
415 {
416 vtkWriter = std::make_unique<VTKOutputModule>(*gridVariables, sol, problem->name());
417 GetPropType<TypeTag, Properties::IOFields>::initOutputModule(*vtkWriter);
418 vtkWriter->addVelocityOutput(
419 std::make_shared<PorousMediumFlowVelocityOutput<
420 GridVariables, GetPropType<TypeTag, Properties::FluxVariables>
421 >>(*gridVariables)
422 );
423 vtkWriter->addField(problem->spatialParams().getRadii(), "radius");
424 vtkWriter->addField(problem->spatialParams().getViscosityFactors(), "vessel tortuosity factor");
425 vtkWriter->write(0.0, Dune::VTK::OutputType::appendedraw);
426 }
427
428 using Assembler = FVAssembler<TypeTag, DiffMethod::analytic>;
429
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 auto assembler = std::make_shared<Assembler>(problem, gridGeometry, gridVariables);
430 using LinearSolver = UMFPackIstlSolver<SeqLinearSolverTraits, LinearAlgebraTraitsFromAssembler<Assembler>>;
431
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>();
432 using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
433
8/20
✓ 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 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
5 NewtonSolver nonLinearSolver(assembler, linearSolver);
434
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 nonLinearSolver.solve(sol);
435
436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (writeVTK)
437 vtkWriter->write(1.0, Dune::VTK::OutputType::appendedraw);
438
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 std::cout << "Flow computation took " << timer.elapsed() << " seconds." << std::endl;
439
440
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.
4 return problem->computeVolumeFluxes(sol, *gridVariables);
441 }
442
443 } // end namespace Dumux
444
445 #endif
446