GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/examples/embedded_network_1d3d/problem.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 85 95 89.5%
Functions: 7 14 50.0%
Branches: 73 158 46.2%

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_TISSUE_NETWORK_TRANSPORT_PROBLEMS_HH
9 #define DUMUX_TISSUE_NETWORK_TRANSPORT_PROBLEMS_HH
10
11 // # Initial, boundary conditions and sources (`problem.hh`)
12 //
13 // This file contains the __problem classes__ which defines the initial and boundary
14 // conditions and implements the coupling source terms. The file contains two
15 // problem classes: `TissueTransportProblem` and `NetworkTransportProblem` for the
16 // respective subdomains. The subdomain problem classes specify boundary and initial
17 // conditions for the subdomains separately. For this setup, we specify boundary fluxes
18 // via the `neumann` function (note that despite its name, the function allows you to
19 // implement both Neumann or Robin-type boundary conditions, weakly imposed).
20 //
21 // The subdomain problems are coupled to each other. This is evident from the
22 // coupling manager pointer that is stored in each subdomain problem (and the
23 // interface function `couplingManager()` giving access to the coupling manager object).
24 // This access is used in the `addPointSources()` and `pointSource(...)` functions.
25 // One point source (in this context) represents a quadrature point for the coupling
26 // condition integral. This means, we implement
27 //
28 // ```math
29 // \vert P \vert C_M D \bar{\varrho} (x^\bigcirc_\mathrm{T} - x_\mathrm{B}) w_i \mathrm{d}s_i
30 // ```
31 //
32 // where $`w_i`$ is the weight and $`\mathrm{d}s_i`$ (units of m) the integration element at
33 // the quadrature point. The units of the resulting term is mol/s (tracer amount per meter and second),
34 // which are the units of the one-dimensional balance equation integrated over one dimensional control volumes.
35 // We are integrating conceptually over the surface of the vessel. The quantity
36 // $`x^\bigcirc_\mathrm{T}`$ is the perimeter average of the 3D mole fraction field. This is not
37 // directly visible in the code since the chosen coupling manager determined what to return here
38 // for the 1D and 3D mole fraction depending on the coupling scheme.
39 //
40 // [[content]]
41 //
42 // ### Include headers
43 // We use properties (compile-time parameterization) and parameters (run-time parameterization).
44 // Moreover, we need array types and the problem base class for porous medium problems.
45 #include <dumux/common/parameters.hh>
46 #include <dumux/common/properties.hh>
47 #include <dumux/common/boundarytypes.hh>
48 #include <dumux/common/numeqvector.hh>
49 #include <dumux/porousmediumflow/problem.hh>
50 //
51 // # The `TissueTransportProblem` class
52 // We start with the tissue transport with boundary, initial condition and sources.
53 // To set the initial condition, the problem reads some parameters from the configuration file
54 // `params.input`. Concentration is defined by $`c = \varrho x`$. This is usually a more
55 // convenient quantity which is why we read this from the configuration file.
56 // (What we read from the configuration file is entirely up to us. You can simply swap
57 // the parameter name in the `getParam` command and adapt the configuration file to provide the parameter.)
58 //
59 // [[codeblock]]
60 namespace Dumux {
61 template <class TypeTag>
62 class TissueTransportProblem : public PorousMediumFlowProblem<TypeTag>
63 {
64 // [[/codeblock]]
65 // [[details]] alias definitions and local variables
66 // [[codeblock]]
67 using ParentType = PorousMediumFlowProblem<TypeTag>;
68 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
69
70 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
71 using GridView = typename GridGeometry::GridView;
72 using FVElementGeometry = typename GridGeometry::LocalView;
73 using SubControlVolume = typename GridGeometry::SubControlVolume;
74 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
75
76 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
77 using ResidualVector = Dumux::NumEqVector<PrimaryVariables>;
78 using BoundaryTypes = Dumux::BoundaryTypes<PrimaryVariables::size()>;
79 using PointSource = GetPropType<TypeTag, Properties::PointSource>;
80
81 static constexpr int dim = GridView::dimension;
82 static constexpr int dimworld = GridView::dimensionworld;
83
84 using Element = typename GridView::template Codim<0>::Entity;
85 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
86
87 using CouplingManager = GetPropType<TypeTag, Properties::CouplingManager>;
88
89 static constexpr int phaseIdx = 0;
90 static constexpr int compIdx = 0;
91
92 static constexpr auto lowDimIdx = typename CouplingManager::MultiDomainTraits::template SubDomain<1>::Index();
93 // [[/codeblock]]
94 // [[/details]]
95 // [[codeblock]]
96 public:
97 1 TissueTransportProblem(std::shared_ptr<const GridGeometry> gridGeometry,
98 std::shared_ptr<CouplingManager> couplingManager,
99 const std::string& paramGroup = "")
100 : ParentType(gridGeometry, paramGroup)
101
2/8
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
5 , couplingManager_(couplingManager)
102 {
103 //read parameters from input file
104
4/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
1 name_ = getParam<std::string>("Problem.Name") + "_3d_transport";
105
106
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 freeD_ = getParam<Scalar>("Tracer.DiffusionCoefficient");
107
108
1/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 initialPeakConcentration_ = getParam<Scalar>("Tissue.Problem.InitialPeakConcentration", 1.0); // mmol/l
109
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 initialCenter_ = getParam<GlobalPosition>("Tissue.Problem.InitialCenter");
110
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 initialStddev_ = getParam<GlobalPosition>("Tissue.Problem.InitialStddev");
111 1 }
112
113 // name (used for output)
114 const std::string& name() const
115
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 { return name_; }
116 // [[/codeblock]]
117 //
118 // We set the initial condition as a Gaussian
119 //
120 // ```math
121 // x(t=0) = \frac{c}{\varrho} \operatorname{exp}\left( -\frac{x-x_0}{2 \sigma_x^2}
122 // -\frac{y-y_0}{2 \sigma_y^2}-\frac{z-z_0}{2 \sigma_z^2} \right)
123 //```
124 //
125 // if the Gaussian is very wide, this essentially corresponds to a constant value.
126 //
127 // [[codeblock]]
128 // initial conditions (called when setting initial solution)
129 8000 PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const
130 {
131 return PrimaryVariables({
132 16000 initialPeakConcentration_/1000*0.018*std::exp(
133 56000 -(globalPos[0] - initialCenter_[0])*(globalPos[0] - initialCenter_[0])/(2*initialStddev_[0]*initialStddev_[0])
134 56000 -(globalPos[1] - initialCenter_[1])*(globalPos[1] - initialCenter_[1])/(2*initialStddev_[1]*initialStddev_[1])
135 56000 -(globalPos[2] - initialCenter_[2])*(globalPos[2] - initialCenter_[2])/(2*initialStddev_[2]*initialStddev_[2])
136 )
137 16000 });
138 }
139 // [[/codeblock]]
140
141 // We set the boundary condition to boundary flux (or Neumann conditions)
142 // and specify zero flux everywhere for the tissue domain
143 //
144 // [[codeblock]]
145 BoundaryTypes boundaryTypesAtPos(const GlobalPosition& globalPos) const
146 {
147
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 242400 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 242400 times.
484800 BoundaryTypes values;
148
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 242400 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 242400 times.
484800 values.setAllNeumann();
149 return values;
150 }
151
152 // flux boundaries (called for Neumann boundaries)
153 template<class ElementVolumeVariables, class ElementFluxVarsCache>
154 ResidualVector neumann(const Element& element,
155 const FVElementGeometry& fvGeometry,
156 const ElementVolumeVariables& elemVolVars,
157 const ElementFluxVarsCache& fluxCache,
158 const SubControlVolumeFace& scvf) const
159 {
160 // no-flow conditions / symmetry conditions
161 484800 ResidualVector values(0.0);
162 return values;
163 }
164 // [[/codeblock]]
165
166 // Now follows the implementation of the point sources. The point sources
167 // are obtained from (and computed by) the coupling manager. The function
168 // `addPointSources` is called when we call `problem->computePointSourceMap()`
169 // in the `main.cc`. The mechanism is provided by the base problem we inherit
170 // from. Essentially all point sources computed by the coupling manager are
171 // located and assigned to the respective control volume. Finally, the
172 // function `pointSource` implements the actual value of the point source.
173 // (While this is linear in the primary variable here, note that you can
174 // also implement non-linear relations here, provided that a Newton solver
175 // is used in the main program.) The `source(...)` function allows to
176 // specify additional volumetric source terms (in units of mol/s/m^3),
177 // for example, some metabolic demand.
178 //
179 // [[codeblock]]
180 // this is needed for the 1d-3d coupling (realized via point source interface)
181 void addPointSources(std::vector<PointSource>& pointSources) const
182
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 { pointSources = this->couplingManager().bulkPointSources(); }
183
184 // called for every point source (coupling term integration point)
185 template<class ElementVolumeVariables>
186 322387 void pointSource(PointSource& source,
187 const Element &element,
188 const FVElementGeometry& fvGeometry,
189 const ElementVolumeVariables& elemVolVars,
190 const SubControlVolume &scv) const
191 {
192 // compute source at every integration point
193 967161 const Scalar x1D = this->couplingManager().lowDimPriVars(source.id())[compIdx];
194 967161 const Scalar x3D = this->couplingManager().bulkPriVars(source.id())[compIdx];
195
196 // get the segment radius (outer radius)
197 967161 const Scalar radius = this->couplingManager().radius(source.id());
198
199 // molar density (mol/m^3) (we assemble a mole balance equation instead of mass balance)
200 322387 const Scalar meanRhoMolar = 1000/0.018;
201
202 // trans-membrane diffusive permeability
203 967161 const auto lowDimElementIdx = this->couplingManager().pointSourceData(source.id()).lowDimElementIdx();
204 644774 const Scalar lc = freeD_
205 1289548 * this->couplingManager().problem(lowDimIdx).spatialParams().membraneFactor(lowDimElementIdx); // m/s
206
207 // diffusive flux across membrane
208 322387 auto transMembraneFlux = -2*M_PI*radius*lc*meanRhoMolar*(x3D - x1D);
209 322387 transMembraneFlux *= source.quadratureWeight()*source.integrationElement();
210
211 644774 source = transMembraneFlux;
212 322387 }
213
214 // additional volumetric source term in mol/(s*m^3), i.e. metabolic consumption
215 // positive value means production into tissue, negative value means extraction from tissue
216 template<class ElementVolumeVariables>
217 ResidualVector source(const Element &element,
218 const FVElementGeometry& fvGeometry,
219 const ElementVolumeVariables& elemVolVars,
220 const SubControlVolume &scv) const
221 {
222
4/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 808000 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 808000 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3323 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3323 times.
✗ Branch 11 not taken.
1634138 return { 0.0 };
223 }
224 // [[/codeblock]]
225
226 // Compute the current contrast agent amount in mole in the whole tissue
227 // This function is used from the main file to write output.
228 //
229 // [[codeblock]]
230 template<class SolutionVector, class GridVariables>
231 101 Scalar computeTracerAmount(const SolutionVector& sol, const GridVariables& gridVars)
232 {
233 101 Scalar totalAmount(0.0);
234
2/4
✓ Branch 1 taken 101 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 101 times.
✗ Branch 5 not taken.
202 auto fvGeometry = localView(this->gridGeometry());
235
2/4
✓ Branch 1 taken 101 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 101 times.
✗ Branch 5 not taken.
202 auto elemVolVars = localView(gridVars.curGridVolVars());
236
4/8
✓ Branch 1 taken 101 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 101 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 101 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 808101 times.
✗ Branch 10 not taken.
1616404 for (const auto& element : elements(this->gridGeometry().gridView()))
237 {
238 808000 fvGeometry.bindElement(element);
239 808000 elemVolVars.bindElement(element, fvGeometry, sol);
240
241
4/4
✓ Branch 2 taken 808000 times.
✓ Branch 3 taken 808000 times.
✓ Branch 4 taken 808000 times.
✓ Branch 5 taken 808000 times.
3232000 for (const auto& scv : scvs(fvGeometry))
242 {
243 808000 const auto& volVars = elemVolVars[scv];
244 808000 const auto localAmount = volVars.porosity()
245 2424000 *volVars.moleFraction(phaseIdx, compIdx)*volVars.molarDensity(phaseIdx)
246 808000 *scv.volume()*volVars.extrusionFactor();
247 808000 totalAmount += localAmount;
248 }
249 }
250
251 101 return totalAmount;
252 }
253 // [[/codeblock]]
254
255 // [[details]] coupling manager interface function and private variables
256 // [[codeblock]]
257 // Get the coupling manager
258 const CouplingManager& couplingManager() const
259
6/12
✗ Branch 6 not taken.
✓ Branch 7 taken 322387 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 322387 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 322387 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 322387 times.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1289550 { return *couplingManager_; }
260
261 private:
262 static constexpr Scalar eps_ = 1.5e-7;
263 std::string name_;
264
265 Scalar freeD_;
266 Scalar initialPeakConcentration_;
267 GlobalPosition initialCenter_, initialStddev_;
268
269 std::shared_ptr<CouplingManager> couplingManager_;
270 };
271 // [[/codeblock]]
272 // [[/details]]
273 //
274 // # The `NetworkTransportProblem` class
275 // We continue with the network transport with boundary, initial condition and sources.
276 // The implementation is quite similar to the tissue domain.
277 // This time the boundary function is more complex as we also take into account
278 // advective transport over the network boundaries to blood flow.
279 //
280 // [[codeblock]]
281 template <class TypeTag>
282 class NetworkTransportProblem : public PorousMediumFlowProblem<TypeTag>
283 {
284 // [[/codeblock]]
285 // [[details]] alias definitions and local variables
286 // [[codeblock]]
287 using ParentType = PorousMediumFlowProblem<TypeTag>;
288
289 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
290 using PointSource = GetPropType<TypeTag, Properties::PointSource>;
291 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
292 using ResidualVector = Dumux::NumEqVector<PrimaryVariables>;
293 using BoundaryTypes = Dumux::BoundaryTypes<PrimaryVariables::size()>;
294
295 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
296 using GridView = typename GridGeometry::GridView;
297 using FVElementGeometry = typename GridGeometry::LocalView;
298 using SubControlVolume = typename GridGeometry::SubControlVolume;
299 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
300
301 using Element = typename GridView::template Codim<0>::Entity;
302 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
303
304 using CouplingManager = GetPropType<TypeTag, Properties::CouplingManager>;
305
306 static constexpr int dim = GridView::dimension;
307 static constexpr int dimworld = GridView::dimensionworld;
308 static constexpr int compIdx = 0;
309 static constexpr int phaseIdx = 0;
310 // [[/codeblock]]
311 // [[/details]]
312 // [[codeblock]]
313 public:
314 // initialize problem instance
315 template<class GridData>
316 1 NetworkTransportProblem(std::shared_ptr<const GridGeometry> gridGeometry,
317 std::shared_ptr<CouplingManager> couplingManager,
318 std::shared_ptr<GridData> gridData,
319 const std::string& paramGroup = "")
320 : ParentType(gridGeometry, paramGroup)
321
2/8
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
3 , couplingManager_(couplingManager)
322 {
323 //read parameters from input file
324
4/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
1 name_ = getParam<std::string>("Problem.Name") + "_1d_transport";
325
326 // initial conditions
327
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 initialNetworkConcentration_ = getParam<Scalar>("Network.Problem.InitialConcentration", 0.0); // mmol/l
328
329 // cross end-feet transport
330
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 freeD_ = getParam<Scalar>("Tracer.DiffusionCoefficient");
331
332 // clearance at sides by diffusion
333 // a boundaryMembraneCoefficient_ of zero means zero gradient / zero diffusive flux
334 // we can still have advective transport
335
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 farFieldConcentration_ = getParam<Scalar>("Network.Problem.FarFieldConcentration", 0.0); // mmol/l
336
1/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 boundaryMembraneCoefficient_ = getParam<Scalar>("Network.Problem.BoundaryMembraneCoefficient", 0.0); // dimensionless
337
338
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);
339 1 }
340
341 // name (used for output)
342 const std::string& name() const
343
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 { return name_; }
344 // [[/codeblock]]
345 // initial conditions (called when setting initial solution)
346 // convert concentration to mole fraction
347 // [[codeblock]]
348 PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const
349 3470 { return { initialNetworkConcentration_/1000*0.018 }; }
350 // [[/codeblock]]
351 //
352 // Set the boundary conditions. Note that we generalize the boundary conditions
353 // for diffusion to allow for a Robin-type boundary condition with a "far-field"
354 // concentration. This can be used to relax the constraint that there is absolutely
355 // no diffusive flux over the boundary (`coeff` $`= 0`$).
356 //
357 // [[codeblock]]
358 // type of boundary condition
359 BoundaryTypes boundaryTypes(const Element& element, const SubControlVolumeFace& scvf) const
360 {
361
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12726 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12726 times.
25452 BoundaryTypes bcTypes;
362
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12726 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12726 times.
25452 bcTypes.setAllNeumann(); // Robin / flux boundary conditions
363 return bcTypes;
364 }
365
366 // flux boundaries (called for Neumann boundaries)
367 template<class ElementVolumeVariables, class ElementFluxVarsCache>
368 12726 ResidualVector neumann(const Element& element,
369 const FVElementGeometry& fvGeometry,
370 const ElementVolumeVariables& elemVolVars,
371 const ElementFluxVarsCache& fluxCache,
372 const SubControlVolumeFace& scvf) const
373 {
374 12726 ResidualVector values(0.0);
375
376 // Robin type boundary condition with far field concentration c
377 // and conductance coefficient (dimensionless)
378 // -> 1.0 means the concentration c reached in 1 µm distance from the boundary
379 // -> if this coefficient is low this essentially means no-flow, if high this means direct outflow/inflow
380 const auto robinFlux = [&](const auto& vv, const Scalar c, const Scalar coeff)
381 {
382
2/2
✓ Branch 0 taken 5858 times.
✓ Branch 1 taken 6868 times.
12726 return - (c/vv.molarDensity() - vv.moleFraction(0, compIdx))
383 12726 *vv.molarDensity()
384
2/2
✓ Branch 0 taken 5858 times.
✓ Branch 1 taken 6868 times.
12726 *coeff * vv.effectiveDiffusionCoefficient(phaseIdx, phaseIdx, compIdx);
385 };
386
387 25452 const auto& volVars = elemVolVars[scvf.insideScvIdx()];
388
389 // diffusive part
390
2/2
✓ Branch 0 taken 5858 times.
✓ Branch 1 taken 6868 times.
12726 values[0] = robinFlux(volVars, farFieldConcentration_, boundaryMembraneCoefficient_);
391
392 // advection
393
4/4
✓ Branch 0 taken 5858 times.
✓ Branch 1 taken 6868 times.
✓ Branch 2 taken 5858 times.
✓ Branch 3 taken 6868 times.
25452 const auto volumeFlux = this->spatialParams().volumeFlux(scvf.index());
394
2/2
✓ Branch 0 taken 5858 times.
✓ Branch 1 taken 6868 times.
12726 if (volumeFlux > 0) // outflow
395 11716 values[0] += volumeFlux*volVars.molarDensity()*volVars.moleFraction(0, compIdx)/(volVars.extrusionFactor()*scvf.area());
396
397 12726 return values;
398 }
399 // [[/codeblock]]
400 //
401 // The point source implementation is symmetric to the implementation of the
402 // tissue domain. This is important such that the coupling condition is implemented
403 // in a mass-conservative way.
404 //
405 // [[codeblock]]
406 // this is needed for the 1d-3d coupling (realized via point source interface)
407 void addPointSources(std::vector<PointSource>& pointSources) const
408
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 { pointSources = this->couplingManager().lowDimPointSources(); }
409
410 // called for every point source (coupling term integration point)
411 template<class ElementVolumeVariables>
412 309825 void pointSource(PointSource& source,
413 const Element& element,
414 const FVElementGeometry& fvGeometry,
415 const ElementVolumeVariables& elemVolVars,
416 const SubControlVolume& scv) const
417 {
418 // compute source at every integration point
419 929475 const Scalar x1D = this->couplingManager().lowDimPriVars(source.id())[compIdx];
420 929475 const Scalar x3D = this->couplingManager().bulkPriVars(source.id())[compIdx];
421
422 // get the segment radius (outer PVS radius)
423 929475 const Scalar radius = this->couplingManager().radius(source.id());
424
425 // molar density (mol/m^3) (we assemble a mole balance equation instead of mass balance)
426 309825 const Scalar meanRhoMolar = 1000/0.018;
427
428 // trans-membrane diffusive permeability
429 619650 const Scalar lc = freeD_
430 619650 * this->spatialParams().membraneFactor(scv.elementIndex()); // m/s
431
432 // diffusive flux across membrane
433 309825 auto transMembraneFlux = 2*M_PI*radius*lc*meanRhoMolar*(x3D - x1D);
434 309825 transMembraneFlux *= source.quadratureWeight()*source.integrationElement();
435
436 619650 source = transMembraneFlux;
437 309825 }
438
439 // additional volumetric source term in mol/(s*m^3), i.e. metabolic consumption
440 // positive value means production into blood, negative value means extraction from blood
441 template<class ElementVolumeVariables>
442 ResidualVector source(const Element &element,
443 const FVElementGeometry& fvGeometry,
444 const ElementVolumeVariables& elemVolVars,
445 const SubControlVolume &scv) const
446 {
447
2/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 175235 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 175235 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
369374 return { 0.0 };
448 }
449 // [[/codeblock]]
450 // [[details]] coupling manager function and internal variables (visibility: private)
451 // [[codeblock]]
452 // The coupling manager
453 const CouplingManager& couplingManager() const
454
2/4
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
1239302 { return *couplingManager_; }
455
456 private:
457 std::string name_;
458
459 // parameters
460 Scalar freeD_;
461
462 Scalar initialNetworkConcentration_; // mmol/l
463 Scalar farFieldConcentration_; // mmol/l
464 Scalar boundaryMembraneCoefficient_; // dimensionless
465
466 std::shared_ptr<CouplingManager> couplingManager_;
467 };
468
469 } //end namespace Dumux
470 // [[/codeblock]]
471 // [[/details]]
472 // [[/content]]
473 #endif
474