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_NETWORK_TISSUE_SPATIAL_PARAMS_HH | ||
9 | #define DUMUX_NETWORK_TISSUE_SPATIAL_PARAMS_HH | ||
10 | |||
11 | // # Spatial parameters (`spatialparams.hh`) | ||
12 | // | ||
13 | // This file contains the __Spatial parameter classes__ for each of the | ||
14 | // sub-problems. This header implements two classes: `TissueSpatialParams` | ||
15 | // and `NetworkSpatialParams`. | ||
16 | // | ||
17 | // [[content]] | ||
18 | // | ||
19 | // ### Include headers | ||
20 | // | ||
21 | #include <dune/common/fvector.hh> | ||
22 | #include <dumux/common/parameters.hh> | ||
23 | #include <dumux/porousmediumflow/fvspatialparams1p.hh> | ||
24 | // | ||
25 | // # The `TissueSpatialParams` class | ||
26 | // | ||
27 | // The tissue spatial parameter are relatively simple. | ||
28 | // All parameters are constant and are configured via the configuration file. | ||
29 | // This means the parameters can be changed at runtime (after compilation). | ||
30 | // | ||
31 | // [[codeblock]] | ||
32 | namespace Dumux { | ||
33 | template<class FVGridGeometry, class Scalar> | ||
34 |
1/6✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | class TissueSpatialParams |
35 | : public FVPorousMediumFlowSpatialParamsOneP<FVGridGeometry, Scalar, TissueSpatialParams<FVGridGeometry, Scalar>> | ||
36 | { | ||
37 | // [[/codeblock]] | ||
38 | // [[details]] alias definitions | ||
39 | // [[codeblock]] | ||
40 | using ThisType = TissueSpatialParams<FVGridGeometry, Scalar>; | ||
41 | using ParentType = FVPorousMediumFlowSpatialParamsOneP<FVGridGeometry, Scalar, ThisType>; | ||
42 | using GridView = typename FVGridGeometry::GridView; | ||
43 | using FVElementGeometry = typename FVGridGeometry::LocalView; | ||
44 | using SubControlVolume = typename FVGridGeometry::SubControlVolume; | ||
45 | using SubControlVolumeFace = typename FVGridGeometry::SubControlVolumeFace; | ||
46 | using Element = typename GridView::template Codim<0>::Entity; | ||
47 | using GlobalPosition = typename Element::Geometry::GlobalCoordinate; | ||
48 | // [[/codeblock]] | ||
49 | // [[/details]] alias definitions | ||
50 | // | ||
51 | // We read parameter from the configuration file. In this case | ||
52 | // all parameters are constants and are configurable at runtime | ||
53 | // through the configuration file. | ||
54 | // | ||
55 | // [[codeblock]] | ||
56 | public: | ||
57 | 1 | TissueSpatialParams(std::shared_ptr<const FVGridGeometry> fvGridGeometry) | |
58 |
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.
|
1 | : ParentType(fvGridGeometry) |
59 | { | ||
60 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | porosity_ = getParam<Scalar>("Tissue.SpatialParams.Porosity"); |
61 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | fluidDensity_ = getParam<Scalar>("Fluid.LiquidDensity", 1000); |
62 |
1/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | fluidMolarMass_ = getParam<Scalar>("Fluid.AverageMolarMass", 0.018); |
63 | 1 | } | |
64 | |||
65 | // porosity of the tissue | ||
66 | ✗ | Scalar porosityAtPos(const GlobalPosition& globalPos) const | |
67 | ✗ | { return porosity_; } | |
68 | // [[/codeblock]] | ||
69 | // | ||
70 | // The volume flux (interstitial fluid flow) is zero | ||
71 | // because we assume no relevant advection takes place. | ||
72 | // | ||
73 | // [[codeblock]] | ||
74 | template<class ElementVolumeVariables> | ||
75 | ✗ | Scalar volumeFlux(const Element &element, | |
76 | const FVElementGeometry& fvGeometry, | ||
77 | const ElementVolumeVariables& elemVolVars, | ||
78 | const SubControlVolumeFace& scvf) const | ||
79 | { | ||
80 | ✗ | return 0.0; | |
81 | } | ||
82 | // [[/codeblock]] | ||
83 | // | ||
84 | // The following interfaces are needed by the (relatively general) | ||
85 | // tracer model to compute the fluid state and the variables needed | ||
86 | // to evaluate the discrete model equation in the local residual. | ||
87 | // The constant temperature is needed for isothermal problem since | ||
88 | // some interfaces (generic material interfaces) sometimes require temperature | ||
89 | // as input. However, this does not mean that this temperature is in | ||
90 | // fact used. | ||
91 | // | ||
92 | // [[details]] fluid density, molar mass, temperature and private variables | ||
93 | // [[codeblock]] | ||
94 | // fluid density | ||
95 | ✗ | Scalar fluidDensity(const Element& element, const SubControlVolume& scv) const | |
96 | ✗ | { return fluidDensity_; } | |
97 | |||
98 | // fluid molar mass | ||
99 | ✗ | Scalar fluidMolarMass(const Element& element, const SubControlVolume& scv) const | |
100 | ✗ | { return fluidMolarMass_; } | |
101 | |||
102 | // This unused here but a required interface for isothermal problems | ||
103 | // passed to fluid property interfaces that may in general depend on temperature | ||
104 | Scalar temperature() const | ||
105 | { return 273.15 + 37.0; } | ||
106 | |||
107 | private: | ||
108 | Scalar porosity_; | ||
109 | Scalar fluidDensity_, fluidMolarMass_; | ||
110 | }; | ||
111 | //[[/codeblock]] | ||
112 | //[[/details]] | ||
113 | // | ||
114 | // # The `NetworkSpatialParams` class | ||
115 | // | ||
116 | // The network parameters contain two additional interfaces. | ||
117 | // First, the parameters from the grid are read in `readGridParams` | ||
118 | // called by the problem class that stores an owning point to the | ||
119 | // spatial parameters object. Second, the `extrusionFactor` interface | ||
120 | // is used to implement extrusion of a line to a cylinder by multiplying | ||
121 | // all areas with the cross-sectional area. Since the cross-sectional | ||
122 | // are depends on the radius this is a spatially-varying parameter. | ||
123 | // `extrusionFactor` always exists as a member function of the base class | ||
124 | // `FVPorousMediumFlowSpatialParamsOneP` and defaults to $`1.0`$ (no extrusion). | ||
125 | // | ||
126 | // [[codeblock]] | ||
127 | template<class GridGeometry, class Scalar> | ||
128 | class NetworkSpatialParams | ||
129 | : public FVPorousMediumFlowSpatialParamsOneP<GridGeometry, Scalar, NetworkSpatialParams<GridGeometry, Scalar>> | ||
130 | { | ||
131 | // [[/codeblock]] | ||
132 | // | ||
133 | // [[details]] alias definitions | ||
134 | // [[codeblock]] | ||
135 | using ThisType = NetworkSpatialParams<GridGeometry, Scalar>; | ||
136 | using ParentType = FVPorousMediumFlowSpatialParamsOneP<GridGeometry, Scalar, ThisType>; | ||
137 | using GridView = typename GridGeometry::GridView; | ||
138 | using FVElementGeometry = typename GridGeometry::LocalView; | ||
139 | using SubControlVolume = typename GridGeometry::SubControlVolume; | ||
140 | using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace; | ||
141 | using Element = typename GridView::template Codim<0>::Entity; | ||
142 | using GlobalPosition = typename Element::Geometry::GlobalCoordinate; | ||
143 | static constexpr int dimWorld = GridView::dimensionworld; | ||
144 | // [[/codeblock]] | ||
145 | // [[/details]] | ||
146 | // | ||
147 | // In the constructor, read several parameters from the configuration file | ||
148 | // [[codeblock]] | ||
149 | public: | ||
150 | 1 | NetworkSpatialParams(std::shared_ptr<const GridGeometry> gridGeometry) | |
151 |
6/22✓ Branch 2 taken 1 times.
✗ Branch 3 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 not taken.
✗ Branch 21 not taken.
✗ 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.
|
5 | : ParentType(gridGeometry) |
152 | { | ||
153 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | fluidDensity_ = getParam<Scalar>("Fluid.LiquidDensity", 1000); |
154 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | fluidMolarMass_ = getParam<Scalar>("Fluid.AverageMolarMass", 0.018); |
155 |
1/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | membraneDiffusionFactor_ = getParam<Scalar>("Tracer.MembraneDiffusionFactor", 1e4); // 1/m |
156 | 1 | } | |
157 | // [[/codeblock]] | ||
158 | // | ||
159 | // Some interface functions that can be used, for example, in the problem class, to | ||
160 | // access spatial parameters. The interface `radius` is required by the 1D-3D coupling | ||
161 | // manager and is used to create the integration points for the coupling term | ||
162 | // | ||
163 | // [[codeblock]] | ||
164 | // this is used in the coupling so we use the outer radius of the network | ||
165 | Scalar radius(std::size_t eIdxGlobal) const | ||
166 | 11492 | { return outerRadius_[eIdxGlobal];} | |
167 | |||
168 | // the vessel radius (as given in the grid data) | ||
169 | Scalar vesselRadius(std::size_t eIdxGlobal) const | ||
170 | 697470 | { return vesselRadius_[eIdxGlobal];} | |
171 | |||
172 | // The membrane diffusion factor (1/m) to be multiplied with the free diffusion coefficient | ||
173 | ✗ | Scalar membraneFactor(std::size_t) const | |
174 | ✗ | { return membraneDiffusionFactor_; } | |
175 | |||
176 | // The blood volume flux (m^3/s) | ||
177 | Scalar volumeFlux(std::size_t scvfIndex) const | ||
178 |
4/4✓ Branch 0 taken 5858 times.
✓ Branch 1 taken 6868 times.
✓ Branch 2 taken 5858 times.
✓ Branch 3 taken 6868 times.
|
25452 | { return volumeFluxes_[scvfIndex]; } |
179 | |||
180 | // All space is available for flow | ||
181 | ✗ | Scalar porosityAtPos(const GlobalPosition& globalPos) const | |
182 | ✗ | { return 1.0; } | |
183 | |||
184 | // This unused here but a required interface for isothermal problems | ||
185 | // passed to fluid property interfaces that may in general depend on temperature | ||
186 | Scalar temperature() const | ||
187 | { return 273.15 + 37.0; } | ||
188 | |||
189 | // fluid density | ||
190 | ✗ | Scalar fluidDensity(const Element& element, const SubControlVolume& scv) const | |
191 | ✗ | { return fluidDensity_; } | |
192 | |||
193 | // fluid molar mass | ||
194 | ✗ | Scalar fluidMolarMass(const Element& element, const SubControlVolume& scv) const | |
195 | ✗ | { return fluidMolarMass_; } | |
196 | // [[/codeblock]] | ||
197 | |||
198 | // Cross-sectional area of network (computed via vessel lumen cross-sectional area) | ||
199 | // [[codeblock]] | ||
200 | template<class ElementSolution> | ||
201 | ✗ | Scalar extrusionFactor(const Element& element, | |
202 | const SubControlVolume& scv, | ||
203 | const ElementSolution& elemSol) const | ||
204 | { | ||
205 | 1046205 | const auto eIdx = this->gridGeometry().elementMapper().index(element); | |
206 | 348735 | const auto lumenRadius = vesselRadius(eIdx); | |
207 | 348735 | return M_PI*lumenRadius*lumenRadius; | |
208 | } | ||
209 | // [[/codeblock]] | ||
210 | // | ||
211 | // The following interface functions are used in the `main.cc` file | ||
212 | // for VTK output. For visualization in ParaView, it is nice to | ||
213 | // write out the vessel radius for ParaView's `Tube` filter. | ||
214 | // | ||
215 | // [[codeblock]] | ||
216 | // Get the vessel lumen radii for output | ||
217 | const std::vector<Scalar>& getVesselRadii() const | ||
218 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | { return vesselRadius_; } |
219 | |||
220 | // Get vessel segment length (for post-processing) | ||
221 | const std::vector<Scalar>& getVesselSegmentLengths() const | ||
222 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | { return vesselSegmentLength_; } |
223 | |||
224 | // Get the outer radii for output | ||
225 | const std::vector<Scalar>& getOuterRadii() const | ||
226 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | { return outerRadius_; } |
227 | // [[/codeblock]] | ||
228 | |||
229 | // Read params from dgf | ||
230 | // the grid file contains the vessel radius for each element | ||
231 | // [[codeblock]] | ||
232 | template<class GridData> | ||
233 | 1 | void readGridParams(const GridData& gridData) | |
234 | { | ||
235 | 1 | const auto& gg = this->gridGeometry(); | |
236 | 2 | const auto numElements = gg.gridView().size(0); | |
237 | 1 | vesselRadius_.resize(numElements); | |
238 | // the vessel segment length | ||
239 | 1 | vesselSegmentLength_.resize(numElements); | |
240 | // outer radius including layers outside lumen that are considered part of the membrane | ||
241 | 1 | outerRadius_.resize(numElements); | |
242 | |||
243 | // The grid view is a leafGridView. Parameters are only set on level 0. | ||
244 | // Elements have to inherit spatial parameters from their father. | ||
245 |
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())) |
246 | { | ||
247 | 1735 | auto level0element = element; | |
248 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1735 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1735 times.
|
3470 | while (level0element.hasFather()) |
249 | ✗ | level0element = level0element.father(); | |
250 | |||
251 | 3470 | const auto eIdx = gg.elementMapper().index(element); | |
252 | 1735 | vesselRadius_[eIdx] = gridData.parameters(level0element)[0]; | |
253 | 1735 | vesselSegmentLength_[eIdx] = element.geometry().volume(); | |
254 | } | ||
255 | |||
256 | // outer radius adding endothelium and basement membrane | ||
257 |
2/2✓ Branch 2 taken 1735 times.
✓ Branch 3 taken 1 times.
|
3471 | for (std::size_t eIdx = 0; eIdx < gg.gridView().size(0); ++eIdx) |
258 | 5205 | outerRadius_[eIdx] = vesselRadius_[eIdx] + 0.4e-6; | |
259 | 1 | } | |
260 | // [[/codeblock]] | ||
261 | // | ||
262 | // The blood volume flux for each (sub)-control-volume face | ||
263 | // is provided from the outside (from a blood-flow solver). | ||
264 | // The advection-diffusion model requires a volume flux | ||
265 | // at each (sub)-control-volume face. In case, for example, | ||
266 | // a velocity field is given instead, volume fluxes can be | ||
267 | // computed using the normal vector `scvf.unitOuterNormal()` | ||
268 | // of the (sub)-control-volume face. | ||
269 | // | ||
270 | // [[codeblock]] | ||
271 | // set the volume fluxes computed by a blood flow model | ||
272 | void setVolumeFluxes(const std::vector<Scalar>& fluxes) | ||
273 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | { volumeFluxes_ = fluxes; } |
274 | |||
275 | template<class ElementVolumeVariables> | ||
276 | ✗ | Scalar volumeFlux(const Element &element, | |
277 | const FVElementGeometry& fvGeometry, | ||
278 | const ElementVolumeVariables& elemVolVars, | ||
279 | const SubControlVolumeFace& scvf) const | ||
280 | { | ||
281 | ✗ | assert(!volumeFluxes_.empty()); | |
282 | ✗ | return volumeFluxes_[scvf.index()]; | |
283 | } | ||
284 | // [[/codeblock]] | ||
285 | // | ||
286 | // [[details]] private member variables | ||
287 | // [[codeblock]] | ||
288 | private: | ||
289 | Scalar porosity_; | ||
290 | Scalar fluidDensity_, fluidMolarMass_; | ||
291 | Scalar membraneDiffusionFactor_; | ||
292 | |||
293 | std::vector<Scalar> vesselRadius_; | ||
294 | std::vector<Scalar> vesselSegmentLength_; | ||
295 | std::vector<Scalar> outerRadius_; | ||
296 | std::vector<Scalar> volumeFluxes_; | ||
297 | }; | ||
298 | |||
299 | } // end namespace Dumux | ||
300 | // [[/codeblock]] | ||
301 | // [[/details]] | ||
302 | // [[/content]] | ||
303 | #endif | ||
304 |