OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
GroundwaterDispersion.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2
11
12#ifndef OPENSWMM_GROUNDWATER_DISPERSION_HPP
13#define OPENSWMM_GROUNDWATER_DISPERSION_HPP
14#include <algorithm>
15#include <array>
16#include <cmath>
18// Inverse-distance least squares; the rank-one limit retains only the
19// resolved direction instead of inventing an unobserved transverse slope.
21 double xx = 0, xy = 0, yy = 0, bx = 0, by = 0;
32 void add(double x, double y, double difference) {
33 const double d = x * x + y * y;
34 if (!(d > 0))
35 return;
36 xx += x * x / d;
37 xy += x * y / d;
38 yy += y * y / d;
39 bx += x * difference / d;
40 by += y * difference / d;
41 }
42
49 std::array<double, 2> value() const {
50 const double trace = xx + yy, det = xx * yy - xy * xy;
51 if (!(trace > 0))
52 return {0, 0};
53 if (det > 1e-12 * trace * trace)
54 return {(yy * bx - xy * by) / det, (xx * by - xy * bx) / det};
55 return {bx / trace, by / trace};
56 }
57};
58struct Tensor {
59 double xx = 0, xy = 0, yy = 0;
66 std::array<double, 2> apply(const std::array<double, 2>& g) const {
67 return {xx * g[0] + xy * g[1], xy * g[0] + yy * g[1]};
68 }
69};
70
80inline Tensor tensor(double vx, double vy, double longitudinal, double transverse,
81 double molecular) {
82 const double speed = std::hypot(vx, vy), base = molecular + transverse * speed;
83 if (!(speed > 0))
84 return {molecular, 0, molecular};
85 const double anisotropy = (longitudinal - transverse) / speed;
86 return {base + anisotropy * vx * vx, anisotropy * vx * vy, base + anisotropy * vy * vy};
87}
88// Harmonic normal resistance with a deferred tangential/nonorthogonal
89// correction. Exact for a linear field and constant tensor on skewed cells.
90// a/b include the water cross-section per unit edge length (theta*h).
113inline double faceFlux(Tensor a, Tensor b, double nx, double ny, double dl, double dr,
114 std::array<double, 2> armL, std::array<double, 2> armR,
115 std::array<double, 2> gradL, std::array<double, 2> gradR, double left,
116 double right, double width) {
117 const auto ag = a.apply(gradL), bg = b.apply(gradR);
118 const double an = nx * (a.xx * nx + a.xy * ny) + ny * (a.xy * nx + a.yy * ny);
119 const double bn = nx * (b.xx * nx + b.xy * ny) + ny * (b.xy * nx + b.yy * ny);
120 if (!(an > 0 && bn > 0 && dl > 0 && dr > 0))
121 return 0;
122 const double crossL =
123 gradL[0] * armL[0] + gradL[1] * armL[1] - dl * (nx * ag[0] + ny * ag[1]) / an;
124 const double crossR =
125 gradR[0] * armR[0] + gradR[1] * armR[1] + dr * (nx * bg[0] + ny * bg[1]) / bn;
126 return width * (left - right + crossL - crossR) / (dl / an + dr / bn);
127}
128}
129#endif
Definition FlowTracer.cpp:25
Definition GroundwaterDispersion.hpp:17
Tensor tensor(double vx, double vy, double longitudinal, double transverse, double molecular)
Form the velocity-aligned mechanical-plus-molecular dispersion tensor.
Definition GroundwaterDispersion.hpp:80
double faceFlux(Tensor a, Tensor b, double nx, double ny, double dl, double dr, std::array< double, 2 > armL, std::array< double, 2 > armR, std::array< double, 2 > gradL, std::array< double, 2 > gradR, double left, double right, double width)
Evaluate a harmonic-normal dispersive exchange with deferred nonorthogonal correction.
Definition GroundwaterDispersion.hpp:113
double * y
Definition odesolve.c:37
Definition GroundwaterDispersion.hpp:20
void add(double x, double y, double difference)
Accumulate one inverse-distance least-squares sample into this fit.
Definition GroundwaterDispersion.hpp:32
double xy
Definition GroundwaterDispersion.hpp:21
double by
Definition GroundwaterDispersion.hpp:21
double xx
Definition GroundwaterDispersion.hpp:21
double yy
Definition GroundwaterDispersion.hpp:21
std::array< double, 2 > value() const
Solve the accumulated planar gradient with a rank-one fallback.
Definition GroundwaterDispersion.hpp:49
double bx
Definition GroundwaterDispersion.hpp:21
Definition GroundwaterDispersion.hpp:58
double yy
Definition GroundwaterDispersion.hpp:59
double xx
Definition GroundwaterDispersion.hpp:59
double xy
Definition GroundwaterDispersion.hpp:59
std::array< double, 2 > apply(const std::array< double, 2 > &g) const
Multiply a two-component gradient by this symmetric tensor.
Definition GroundwaterDispersion.hpp:66