Plugins
Loading...
Searching...
No Matches
manning_roughness_1d.h
Go to the documentation of this file.
1//
2// Created by julian on 1/29/25.
3//
4
5#ifndef D3F_MANNING_ROUGHNESS_1D_H
6#define D3F_MANNING_ROUGHNESS_1D_H
8
9namespace ug {namespace d3f{
17template<int dim>
18class ManningRoughness1d : public StdDataLinker<ManningRoughness1d<dim>, number, dim> {
19
20 // --- Type Definitions ---
25
26public:
27 // Identifiers for the input fields
28 enum inputs { _h_ = 0, _v_, _n_ };
29
31 this->set_num_input(3);
32 }
33
34 // --- Setters ---
35 void set_hmin(number h) { m_hmin = h; } // CRITICAL FIX: Removed stray 'return;'
36 void set_gravity(number gin) { m_g = gin; }
37
39 m_n = n;
40 m_dn = n.template cast_dynamic<TDNumberData>();
41 this->set_input(_n_, n, n);
42 }
43
45 m_h = h;
46 m_dh = h.template cast_dynamic<TDNumberData>();
47 this->set_input(_h_, h, h);
48 }
49
51 m_v = v;
52 m_dv = v.template cast_dynamic<TDNumberData>();
53 this->set_input(_v_, v, v);
54 }
55
56 // --- Evaluation Methods ---
57
58 inline void evaluate(number& value, const MathVector<dim>& globIP, number time, int si) const {
59 UG_THROW("ManningRoughness1d: Not implemented for single global positions.\n");
60 }
61
65 template <int refDim>
66 inline void evaluate(number vValue[],
67 const MathVector<dim> vGlobIP[],
68 number time, int si,
69 GridObject* elem,
70 const MathVector<dim> vCornerCoords[],
71 const MathVector<refDim> vLocIP[],
72 const size_t nip,
73 LocalVector* u,
74 const MathMatrix<refDim, dim>* vJT = NULL) const
75 {
76 // Note: Using VLAs (Variable Length Arrays) here. standard in UG4, but be aware it's a C99/compiler extension.
77 number vVel[nip];
78 number vh[nip];
79 number vn[nip];
80
81 // Evaluate inputs at the integration points
82 (*m_h)(&vh[0], vGlobIP, time, si, elem, vCornerCoords, vLocIP, nip, u, vJT);
83 (*m_v)(&vVel[0], vGlobIP, time, si, elem, vCornerCoords, vLocIP, nip, u, vJT);
84 (*m_n)(&vn[0], vGlobIP, time, si, elem, vCornerCoords, vLocIP, nip, u, vJT);
85
86 for (size_t ip = 0; ip < nip; ++ip) {
87 // Cutoff to prevent division by zero or oscillating signs at near-zero velocities
88 if (std::fabs(vVel[ip]) < m_vmin) {
89 vValue[ip] = 0.0;
90 continue;
91 }
92
93 // Calculate Reaction Rate R = (g * n^2 * |v|) / h^(4/3)
94 vValue[ip] = m_g * vn[ip] * vn[ip] * std::fabs(vVel[ip]);
95 vValue[ip] /= std::pow(std::max(vh[ip], m_hmin), (4.0 / 3.0));
96 }
97 }
98
102 template <int refDim>
103 void eval_and_deriv(number vValue[],
104 const MathVector<dim> vGlobIP[],
105 number time, int si,
106 GridObject* elem,
107 const MathVector<dim> vCornerCoords[],
108 const MathVector<refDim> vLocIP[],
109 const size_t nip,
110 LocalVector* u,
111 bool bDeriv,
112 int s,
113 std::vector<std::vector<number>> vvvDeriv[],
114 const MathMatrix<refDim, dim>* vJT = NULL) const
115 {
116 // 1. Evaluate the base value
117 evaluate<refDim>(vValue, vGlobIP, time, si, elem, vCornerCoords, vLocIP, nip, u, vJT);
118
119 if (!bDeriv) return;
120 if (this->zero_derivative()) return; // CRITICAL FIX: Hoisted out of the integration point loop
121
122 number vVel[nip];
123 number vh[nip];
124 number vn[nip];
125
126 // Re-evaluate inputs to use for derivative calculations
127 (*m_h)(&vh[0], vGlobIP, time, si, elem, vCornerCoords, vLocIP, nip, u, vJT);
128 (*m_v)(&vVel[0], vGlobIP, time, si, elem, vCornerCoords, vLocIP, nip, u, vJT);
129 (*m_n)(&vn[0], vGlobIP, time, si, elem, vCornerCoords, vLocIP, nip, u, vJT);
130
131 this->set_zero(vvvDeriv, nip);
132
133 for (size_t ip = 0; ip < nip; ++ip) {
134 // Calculate partial derivatives analytically
135 number dh = evaluate_dh(vVel[ip], vn[ip], vh[ip], m_g);
136 number dv = evaluate_dv(vVel[ip], vn[ip], vh[ip], m_g);
137 number dn = evaluate_dn(vVel[ip], vn[ip], vh[ip], m_g);
138
139 // --- Derivative w.r.t Depth (h) ---
140 size_t sid = this->series_id(_h_, s);
141 if (m_dh.valid() && !m_dh->zero_derivative()) {
142 for (size_t fct = 0; fct < m_dh->num_fct(); fct++) {
143 const number* vDHeight = m_dh->deriv(sid, ip, fct);
144 const size_t commonFct = this->input_common_fct(_h_, fct);
145
146 if (this->num_sh(commonFct) == nip) {
147 vvvDeriv[ip][commonFct][ip] += dh * vDHeight[ip]; // FV1 mass lumping
148 } else {
149 for (size_t sh = 0; sh < this->num_sh(commonFct); ++sh) {
150 vvvDeriv[ip][commonFct][sh] += dh * vDHeight[sh];
151 }
152 }
153 }
154 }
155
156 // --- Derivative w.r.t Velocity (v) ---
157 sid = this->series_id(_v_, s);
158 if (m_dv.valid() && !m_dv->zero_derivative()) {
159 for (size_t fct = 0; fct < m_dv->num_fct(); fct++) {
160 const number* vDVel = m_dv->deriv(sid, ip, fct);
161 const size_t commonFct = this->input_common_fct(_v_, fct);
162
163 if (this->num_sh(commonFct) == nip) {
164 vvvDeriv[ip][commonFct][ip] += dv * vDVel[ip];
165 } else {
166 for (size_t sh = 0; sh < this->num_sh(commonFct); ++sh) {
167 vvvDeriv[ip][commonFct][sh] += dv * vDVel[sh];
168 }
169 }
170 }
171 }
172
173 // --- Derivative w.r.t Manning's n ---
174 sid = this->series_id(_n_, s);
175 if (m_n.valid() && !m_n->zero_derivative()) {
176 for (size_t fct = 0; fct < m_dn->num_fct(); fct++) {
177 const number* vDn = m_dn->deriv(sid, ip, fct);
178 const size_t commonFct = this->input_common_fct(_n_, fct);
179
180 if (this->num_sh(commonFct) == nip) {
181 vvvDeriv[ip][commonFct][ip] += dn * vDn[ip];
182 } else {
183 for (size_t sh = 0; sh < this->num_sh(commonFct); ++sh) {
184 vvvDeriv[ip][commonFct][sh] += dn * vDn[sh];
185 }
186 }
187 }
188 }
189 }
190 }
191
192 bool requires_grid_fct() const { return true; }
193
194 // --- Analytical Derivatives ---
195
196 // Partial derivative w.r.t velocity: dR/dv
197 number evaluate_dv(const number v, const number n, const number h, const number g) const {
198 // v / fabs(v + SMALL_SQ) acts as a smoothed sign(v) function
199 return g * n * n * v / (std::fabs(v + SMALL_SQ) * std::pow(std::max(h, m_hmin), (4.0 / 3.0)));
200 }
201
202 // Partial derivative w.r.t depth: dR/dh
203 number evaluate_dh(const number v, const number n, const number h, const number g) const {
204 return (-4.0 / 3.0) * g * n * n * std::fabs(v) / std::pow(std::max(h, m_hmin), (7.0 / 3.0));
205 }
206
207 // Partial derivative w.r.t Manning's n: dR/dn
208 number evaluate_dn(const number v, const number n, const number h, const number g) const {
209 return (2.0 * g * n * std::fabs(v)) / std::pow(std::max(h, m_hmin), (4.0 / 3.0));
210 }
211
212private:
219
220 // Member variables standardized with 'm_' prefix
223 number m_g = 9.81 * 60.0 * 60.0; // Gravity, scaled likely for time units (e.g., hours)
224};
225
226
227}
228}// namespace ug
229#endif //MANNING_ROUGHNESS_1D_H
parameterString s
Definition Biogas.lua:2
TData & value(size_t s, size_t ip)
number time() const
const MathVector< dim > & ip(size_t s, size_t ip) const
virtual void set_input(size_t i, SmartPtr< ICplUserData< dim > > input, SmartPtr< UserDataInfo > info)
Calculates the river bottom friction (reaction rate) using Manning's formula.
Definition manning_roughness_1d.h:18
void set_gravity(number gin)
Definition manning_roughness_1d.h:36
void set_h(SmartPtr< TNumberData > h)
Definition manning_roughness_1d.h:44
SmartPtr< TDNumberData > m_dv
Definition manning_roughness_1d.h:214
number m_g
Definition manning_roughness_1d.h:223
number evaluate_dn(const number v, const number n, const number h, const number g) const
Definition manning_roughness_1d.h:208
number evaluate_dh(const number v, const number n, const number h, const number g) const
Definition manning_roughness_1d.h:203
SmartPtr< TDNumberData > m_dh
Definition manning_roughness_1d.h:216
bool requires_grid_fct() const
Definition manning_roughness_1d.h:192
SmartPtr< TNumberData > m_n
Definition manning_roughness_1d.h:217
void evaluate(number &value, const MathVector< dim > &globIP, number time, int si) const
Definition manning_roughness_1d.h:58
DependentUserData< number, dim > TDNumberData
Definition manning_roughness_1d.h:23
SmartPtr< TDNumberData > m_dn
Definition manning_roughness_1d.h:218
void eval_and_deriv(number vValue[], const MathVector< dim > vGlobIP[], number time, int si, GridObject *elem, const MathVector< dim > vCornerCoords[], const MathVector< refDim > vLocIP[], const size_t nip, LocalVector *u, bool bDeriv, int s, std::vector< std::vector< number > > vvvDeriv[], const MathMatrix< refDim, dim > *vJT=NULL) const
Evaluates the value AND the Jacobian (derivatives w.r.t h, v, n) for the Newton solver.
Definition manning_roughness_1d.h:103
SmartPtr< TNumberData > m_v
Definition manning_roughness_1d.h:213
number m_vmin
Definition manning_roughness_1d.h:221
ManningRoughness1d()
Definition manning_roughness_1d.h:30
void set_hmin(number h)
Definition manning_roughness_1d.h:35
void set_v(SmartPtr< TNumberData > v)
Definition manning_roughness_1d.h:50
number m_hmin
Definition manning_roughness_1d.h:222
number evaluate_dv(const number v, const number n, const number h, const number g) const
Definition manning_roughness_1d.h:197
CplUserData< MathVector< dim >, dim > TVectorData
Definition manning_roughness_1d.h:22
CplUserData< number, dim > TNumberData
Definition manning_roughness_1d.h:21
inputs
Definition manning_roughness_1d.h:28
@ _h_
Definition manning_roughness_1d.h:28
@ _n_
Definition manning_roughness_1d.h:28
@ _v_
Definition manning_roughness_1d.h:28
SmartPtr< TNumberData > m_h
Definition manning_roughness_1d.h:215
void evaluate(number vValue[], const MathVector< dim > vGlobIP[], number time, int si, GridObject *elem, const MathVector< dim > vCornerCoords[], const MathVector< refDim > vLocIP[], const size_t nip, LocalVector *u, const MathMatrix< refDim, dim > *vJT=NULL) const
Evaluates the Manning roughness reaction rate at local integration points.
Definition manning_roughness_1d.h:66
void set_manning_coefficient(SmartPtr< TNumberData > n)
Definition manning_roughness_1d.h:38
DependentUserData< MathVector< dim >, dim > TDVectorData
Definition manning_roughness_1d.h:24
#define UG_THROW(msg)
double number
const number SMALL_SQ