PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Functions
wallfunction.h File Reference
#include <petscpf.h>
#include <petscdmswarm.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <petsctime.h>
#include <petscsys.h>
#include <petscdmcomposite.h>
#include <petscsystypes.h>
#include "variables.h"
#include "ParticleSwarm.h"
#include "walkingsearch.h"
#include "grid.h"
#include "logging.h"
#include "io.h"
#include "interpolation.h"
#include "ParticleMotion.h"
#include "Boundaries.h"
Include dependency graph for wallfunction.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void noslip (UserCtx *user, double distance_reference, double distance_boundary, Cmpnts velocity_wall, Cmpnts velocity_reference, Cmpnts *velocity_boundary, double normal_x, double normal_y, double normal_z)
 Applies no-slip wall boundary condition with linear interpolation.
 
void freeslip (UserCtx *user, double distance_reference, double distance_boundary, Cmpnts velocity_wall, Cmpnts velocity_reference, Cmpnts *velocity_boundary, double normal_x, double normal_y, double normal_z)
 Applies free-slip wall boundary condition.
 
double E_coeff (double friction_velocity, double roughness_height, double kinematic_viscosity)
 Computes roughness-modified log-law coefficient E.
 
double u_hydset_roughness (double kinematic_viscosity, double wall_distance, double friction_velocity, double roughness_height)
 Computes velocity from log-law for rough walls.
 
double f_hydset (double kinematic_viscosity, double known_velocity, double wall_distance, double friction_velocity_guess, double roughness_height)
 Residual function for friction velocity equation (log-law with roughness)
 
double df_hydset (double kinematic_viscosity, double known_velocity, double wall_distance, double friction_velocity_guess, double roughness_height)
 Numerical derivative of residual function.
 
double find_utau_hydset (double kinematic_viscosity, double known_velocity, double wall_distance, double initial_guess, double roughness_height)
 Solves for friction velocity using Newton-Raphson iteration.
 
double nu_t (double yplus)
 Computes turbulent eddy viscosity ratio (ν_t / ν)
 
double integrate_1 (double kinematic_viscosity, double wall_distance, double friction_velocity, int integration_mode)
 Integrates eddy viscosity profile from wall to distance y.
 
double taw (double kinematic_viscosity, double friction_velocity, double wall_distance, double velocity, double pressure_gradient_tangent)
 Computes wall shear stress with pressure gradient effects.
 
double u_Cabot (double kinematic_viscosity, double wall_distance, double friction_velocity, double pressure_gradient_tangent, double wall_shear_stress)
 Computes velocity using Cabot wall function.
 
double f_Cabot (double kinematic_viscosity, double velocity, double wall_distance, double friction_velocity_guess, double pressure_gradient_tangent, double pressure_gradient_normal)
 Residual function for Cabot wall function.
 
double df_Cabot (double kinematic_viscosity, double velocity, double wall_distance, double friction_velocity_guess, double pressure_gradient_tangent, double pressure_gradient_normal)
 Numerical derivative for Cabot wall function.
 
void find_utau_Cabot (double kinematic_viscosity, double velocity, double wall_distance, double initial_guess, double pressure_gradient_tangent, double pressure_gradient_normal, double *friction_velocity, double *wall_shear_velocity, double *wall_shear_normal)
 Solves for friction velocity using Cabot wall function.
 
double u_Werner (double kinematic_viscosity, double wall_distance, double friction_velocity)
 Computes velocity using Werner-Wengle wall function.
 
double taw_Werner (double kinematic_viscosity, double velocity, double wall_distance)
 Wall shear stress from the cell-integrated Werner-Wengle relation.
 
double u_Werner_explicit (double kinematic_viscosity, double wall_distance, double wall_shear_stress)
 Wall-parallel velocity at a distance, from the Werner-Wengle wall stress.
 
double find_utau_Werner (double kinematic_viscosity, double velocity, double wall_distance, double initial_guess)
 Friction velocity from a point velocity, inverting u_Werner() exactly.
 
double u_loglaw (double wall_distance, double friction_velocity, double roughness_length)
 Computes velocity using simple log-law (smooth wall with roughness offset)
 
double find_utau_loglaw (double velocity, double wall_distance, double roughness_length)
 Solves for friction velocity using simple log-law (explicit formula)
 
void wall_function (UserCtx *user, double distance_reference, double distance_boundary, Cmpnts velocity_wall, Cmpnts velocity_reference, Cmpnts *velocity_boundary, PetscReal *friction_velocity, double normal_x, double normal_y, double normal_z)
 Applies standard wall function with Werner-Wengle model.
 
void wall_function_loglaw (UserCtx *user, double roughness_height, double distance_reference, double distance_boundary, Cmpnts velocity_wall, Cmpnts velocity_reference, Cmpnts *velocity_boundary, PetscReal *friction_velocity, double normal_x, double normal_y, double normal_z)
 Applies log-law wall function with roughness correction.
 
void wall_function_Cabot (UserCtx *user, double roughness_height, double distance_reference, double distance_boundary, Cmpnts velocity_wall, Cmpnts velocity_reference, Cmpnts *velocity_boundary, PetscReal *friction_velocity, double normal_x, double normal_y, double normal_z, double pressure_gradient_x, double pressure_gradient_y, double pressure_gradient_z, int iteration_count)
 Applies Cabot non-equilibrium wall function with pressure gradients.
 

Function Documentation

◆ noslip()

void noslip ( UserCtx *  user,
double  distance_reference,
double  distance_boundary,
Cmpnts  velocity_wall,
Cmpnts  velocity_reference,
Cmpnts *  velocity_boundary,
double  normal_x,
double  normal_y,
double  normal_z 
)

Applies no-slip wall boundary condition with linear interpolation.

This function enforces a no-slip boundary condition (zero velocity at the wall) by linearly interpolating between the wall velocity (typically zero) and the velocity at a reference point in the flow.

MATHEMATICAL FORMULATION: For a point at distance sb from the wall, with a reference velocity Uc at distance sc from the wall: U_boundary = U_wall + (U_reference - U_wall) * (sb / sc)

PHYSICAL INTERPRETATION: This provides a first-order approximation assuming linear velocity variation in the near-wall region, which is valid in the viscous sublayer.

Parameters
[in]userSimulation context (unused but required for interface)
[in]distance_referenceWall-normal distance to reference point (sc)
[in]distance_boundaryWall-normal distance to boundary point (sb)
[in]velocity_wallVelocity at the wall (Ua), typically zero
[in]velocity_referenceVelocity at reference point (Uc)
[out]velocity_boundaryComputed velocity at boundary point (Ub)
[in]normal_xX-component of wall normal vector
[in]normal_yY-component of wall normal vector
[in]normal_zZ-component of wall normal vector
Note
For moving walls, velocity_wall would be non-zero
The normal vector should point INTO the fluid domain

Applies no-slip wall boundary condition with linear interpolation.

Local to this translation unit.

Definition at line 68 of file wallfunction.c.

73{
74 (void)user;
75 (void)normal_x;
76 (void)normal_y;
77 (void)normal_z;
78 // Compute velocity difference between reference point and wall
79 double delta_u = velocity_reference.x - velocity_wall.x;
80 double delta_v = velocity_reference.y - velocity_wall.y;
81 double delta_w = velocity_reference.z - velocity_wall.z;
82
83 // Linear interpolation factor
84 double interpolation_factor = distance_boundary / distance_reference;
85
86 // Apply linear interpolation
87 (*velocity_boundary).x = interpolation_factor * delta_u;
88 (*velocity_boundary).y = interpolation_factor * delta_v;
89 (*velocity_boundary).z = interpolation_factor * delta_w;
90
91 // Add wall velocity (shift to absolute frame)
92 (*velocity_boundary).x += velocity_wall.x;
93 (*velocity_boundary).y += velocity_wall.y;
94 (*velocity_boundary).z += velocity_wall.z;
95}
PetscScalar x
Definition variables.h:122
PetscScalar z
Definition variables.h:122
PetscScalar y
Definition variables.h:122
Here is the caller graph for this function:

◆ freeslip()

void freeslip ( UserCtx *  user,
double  distance_reference,
double  distance_boundary,
Cmpnts  velocity_wall,
Cmpnts  velocity_reference,
Cmpnts *  velocity_boundary,
double  normal_x,
double  normal_y,
double  normal_z 
)

Applies free-slip wall boundary condition.

Free-slip conditions allow tangential flow but enforce zero normal velocity. This is appropriate for inviscid walls or symmetry planes where there is no shear stress but flow cannot penetrate the boundary.

DECOMPOSITION: Velocity is decomposed into normal and tangential components: U = U_n * n + U_t where U_n = U · n (normal component) U_t = U - U_n * n (tangential component)

BOUNDARY CONDITIONS:

  • Normal component: Interpolated from interior (∂U_n/∂n ≠ 0)
  • Tangential component: Extrapolated from interior (∂U_t/∂n = 0)
Parameters
[in]userSimulation context
[in]distance_referenceWall-normal distance to reference point
[in]distance_boundaryWall-normal distance to boundary point
[in]velocity_wallVelocity at the wall
[in]velocity_referenceVelocity at reference point
[out]velocity_boundaryComputed velocity at boundary point
[in]normal_xX-component of wall normal vector
[in]normal_yY-component of wall normal vector
[in]normal_zZ-component of wall normal vector

Applies free-slip wall boundary condition.

Local to this translation unit.

Definition at line 101 of file wallfunction.c.

106{
107 (void)user;
108 // Extract normal components of velocities
109 double wall_normal_velocity = velocity_wall.x * normal_x +
110 velocity_wall.y * normal_y +
111 velocity_wall.z * normal_z;
112
113 double reference_normal_velocity = velocity_reference.x * normal_x +
114 velocity_reference.y * normal_y +
115 velocity_reference.z * normal_z;
116
117 // Interpolate normal velocity component
118 double boundary_normal_velocity = wall_normal_velocity +
119 (reference_normal_velocity - wall_normal_velocity) * (distance_boundary / distance_reference);
120
121 // Extract tangential velocity components (extrapolated from reference point)
122 double tangential_u = velocity_reference.x - reference_normal_velocity * normal_x;
123 double tangential_v = velocity_reference.y - reference_normal_velocity * normal_y;
124 double tangential_w = velocity_reference.z - reference_normal_velocity * normal_z;
125
126 // Reconstruct total velocity: U = U_t + U_n * n
127 (*velocity_boundary).x = tangential_u + boundary_normal_velocity * normal_x;
128 (*velocity_boundary).y = tangential_v + boundary_normal_velocity * normal_y;
129 (*velocity_boundary).z = tangential_w + boundary_normal_velocity * normal_z;
130}
Here is the caller graph for this function:

◆ E_coeff()

double E_coeff ( double  friction_velocity,
double  roughness_height,
double  kinematic_viscosity 
)

Computes roughness-modified log-law coefficient E.

The coefficient E accounts for wall roughness effects on the log-law: u+ = (1/κ) ln(E * y+)

ROUGHNESS REGIMES:

  1. Hydraulically smooth (ks+ < 2.25): E = exp(κ*B), no roughness effect
  2. Transitional (2.25 < ks+ < 90): Smooth interpolation between regimes
  3. Fully rough (ks+ > 90): E modified by roughness height where ks+ = u_τ * ks / ν (roughness Reynolds number)
Parameters
[in]friction_velocityFriction velocity u_τ
[in]roughness_heightEquivalent sand grain roughness height ks
[in]kinematic_viscosityKinematic viscosity ν
Returns
Roughness-modified log-law coefficient E
Note
This follows the Nikuradse sand grain roughness correlation

Computes roughness-modified log-law coefficient E.

Local to this translation unit.

Definition at line 140 of file wallfunction.c.

141{
142 // Compute roughness Reynolds number
143 double roughness_reynolds = friction_velocity * roughness_height / kinematic_viscosity;
144
145 double roughness_correction;
146
147 if (roughness_reynolds <= ROUGHNESS_TRANSITION_YPLUS) {
148 // Hydraulically smooth regime: no correction needed
149 roughness_correction = 0.0;
150 }
151 else if (roughness_reynolds < FULLY_ROUGH_YPLUS) {
152 // Transitional regime: smooth interpolation using sine function
153 // This provides a gradual transition between smooth and rough wall behavior
154 double max_correction = LOGLAW_B - 8.5 + (1.0 / KAPPA) * log(roughness_reynolds);
155
156 roughness_correction = max_correction *
157 sin(0.4258 * (log(roughness_reynolds) - 0.811));
158 }
159 else {
160 // Fully rough regime: maximum correction
161 roughness_correction = LOGLAW_B - 8.5 + (1.0 / KAPPA) * log(roughness_reynolds);
162 }
163
164 // Return E = exp[κ(B - ΔB)]
165 return exp(KAPPA * (LOGLAW_B - roughness_correction));
166}
#define ROUGHNESS_TRANSITION_YPLUS
Smooth-to-rough transition y+ threshold.
#define LOGLAW_B
Log-law intercept constant B for smooth walls.
#define FULLY_ROUGH_YPLUS
Fully rough regime y+ threshold.
#define KAPPA
von Karman constant (universal turbulence constant)
Here is the caller graph for this function:

◆ u_hydset_roughness()

double u_hydset_roughness ( double  kinematic_viscosity,
double  wall_distance,
double  friction_velocity,
double  roughness_height 
)

Computes velocity from log-law for rough walls.

Calculates the tangential velocity at a given wall distance using the roughness-modified log-law of the wall.

APPLICABLE REGIMES:

  • Viscous sublayer (y+ < 11.53): u+ = y+
  • Log-layer (11.53 < y+ < 300): u+ = (1/κ) ln(E * y+)
  • Outer layer (y+ > 300): Returns -1 (invalid, wake region)
Parameters
[in]kinematic_viscosityKinematic viscosity ν
[in]wall_distanceDistance from wall y
[in]friction_velocityFriction velocity u_τ
[in]roughness_heightEquivalent sand grain roughness ks
Returns
Tangential velocity u_t, or -1 if outside valid range
Note
The upper limit y+ < 300 ensures we stay within the log-layer
For y+ > 300, wake effects become important and log-law is invalid

Computes velocity from log-law for rough walls.

Local to this translation unit.

Definition at line 172 of file wallfunction.c.

174{
175 // Normalized wall distance
176 double yplus = friction_velocity * wall_distance / kinematic_viscosity;
177
178 // Threshold values for regime transitions
179 const double viscous_limit = VISCOUS_SUBLAYER_YPLUS;
180 const double loglayer_limit = 300.0;
181
182 double tangential_velocity;
183
184 if (yplus <= viscous_limit) {
185 // Viscous sublayer: linear velocity profile
186 tangential_velocity = friction_velocity * yplus;
187 }
188 else if (yplus <= loglayer_limit) {
189 // Log-layer: logarithmic velocity profile with roughness correction
190 double E = E_coeff(friction_velocity, roughness_height, kinematic_viscosity);
191 tangential_velocity = (friction_velocity / KAPPA) * log(E * yplus);
192 }
193 else {
194 // Outside valid range (wake region or beyond)
195 tangential_velocity = -1.0;
196 }
197
198 return tangential_velocity;
199}
#define VISCOUS_SUBLAYER_YPLUS
Viscous sublayer thickness y+ threshold.
double E_coeff(double friction_velocity, double roughness_height, double kinematic_viscosity)
Internal helper implementation: E_coeff().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ f_hydset()

double f_hydset ( double  kinematic_viscosity,
double  known_velocity,
double  wall_distance,
double  friction_velocity_guess,
double  roughness_height 
)

Residual function for friction velocity equation (log-law with roughness)

This function computes the residual for Newton-Raphson iteration: f(u_τ) = u_predicted(u_τ) - u_known where u_predicted comes from the log-law or linear law depending on y+.

Parameters
[in]kinematic_viscosityKinematic viscosity
[in]known_velocityKnown velocity at distance y
[in]wall_distanceDistance from wall
[in]friction_velocity_guessCurrent guess for u_τ
[in]roughness_heightWall roughness height
Returns
Residual value (should be zero at solution)

Residual function for friction velocity equation (log-law with roughness)

Local to this translation unit.

Definition at line 209 of file wallfunction.c.

212{
213 double yplus = friction_velocity_guess * wall_distance / kinematic_viscosity;
214 double residual;
215
216 if (yplus <= VISCOUS_SUBLAYER_YPLUS) {
217 // Viscous sublayer: u = u_τ * y+
218 residual = friction_velocity_guess * yplus - known_velocity;
219 }
220 else {
221 // Log-layer: u = (u_τ / κ) * ln(E * y+)
222 double E = E_coeff(friction_velocity_guess, roughness_height, kinematic_viscosity);
223 residual = friction_velocity_guess * (1.0 / KAPPA * log(E * yplus)) - known_velocity;
224 }
225
226 return residual;
227}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ df_hydset()

double df_hydset ( double  kinematic_viscosity,
double  known_velocity,
double  wall_distance,
double  friction_velocity_guess,
double  roughness_height 
)

Numerical derivative of residual function.

Computes df/du_τ using finite differences for Newton-Raphson iteration.

Parameters
[in]kinematic_viscosityKinematic viscosity
[in]known_velocityKnown velocity
[in]wall_distanceDistance from wall
[in]friction_velocity_guessCurrent guess for u_τ
[in]roughness_heightWall roughness
Returns
Derivative df/du_τ

Numerical derivative of residual function.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
df_hydset()

Definition at line 235 of file wallfunction.c.

238{
239 const double perturbation = 1.e-7;
240
241 double f_plus = f_hydset(kinematic_viscosity, known_velocity, wall_distance,
242 friction_velocity_guess + perturbation, roughness_height);
243
244 double f_minus = f_hydset(kinematic_viscosity, known_velocity, wall_distance,
245 friction_velocity_guess - perturbation, roughness_height);
246
247 return (f_plus - f_minus) / (2.0 * perturbation);
248}
double f_hydset(double kinematic_viscosity, double known_velocity, double wall_distance, double friction_velocity_guess, double roughness_height)
Internal helper implementation: f_hydset().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_utau_hydset()

double find_utau_hydset ( double  kinematic_viscosity,
double  known_velocity,
double  wall_distance,
double  initial_guess,
double  roughness_height 
)

Solves for friction velocity using Newton-Raphson iteration.

Given a known velocity at a known distance from the wall, this function iteratively solves for the friction velocity u_τ that satisfies the roughness-modified log-law or linear law.

ALGORITHM: Newton-Raphson: u_τ^(n+1) = u_τ^n - f(u_τ^n) / f'(u_τ^n) Convergence criterion: |u_τ^(n+1) - u_τ^n| < 1e-7

Parameters
[in]kinematic_viscosityKinematic viscosity
[in]known_velocityVelocity at reference point
[in]wall_distanceDistance from wall to reference point
[in]initial_guessInitial guess for u_τ
[in]roughness_heightWall roughness height
Returns
Converged friction velocity u_τ
Note
Maximum 30 iterations; warns if convergence not achieved
Typical convergence in 3-5 iterations for good initial guess

Solves for friction velocity using Newton-Raphson iteration.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
find_utau_hydset()

Definition at line 256 of file wallfunction.c.

259{
260 double friction_velocity = initial_guess;
261 double friction_velocity_old = initial_guess;
262
263 const int max_iterations = 30;
264 const double convergence_tolerance = 1.e-7;
265
266 int iteration;
267 for (iteration = 0; iteration < max_iterations; iteration++) {
268 // Newton-Raphson update
269 double residual = f_hydset(kinematic_viscosity, known_velocity, wall_distance,
270 friction_velocity_old, roughness_height);
271 double derivative = df_hydset(kinematic_viscosity, known_velocity, wall_distance,
272 friction_velocity_old, roughness_height);
273
274 friction_velocity = friction_velocity_old - residual / derivative;
275
276 // Check convergence
277 if (fabs(friction_velocity - friction_velocity_old) < convergence_tolerance) {
278 break;
279 }
280
281 friction_velocity_old = friction_velocity;
282 }
283
284 // Warn if convergence not achieved
285 if (iteration == max_iterations) {
287 "WARNING: u_tau iteration did not converge after %d iterations. "
288 "Final difference: %le\n",
289 iteration, fabs(friction_velocity - friction_velocity_old));
290 }
291
292 return friction_velocity;
293}
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:45
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:200
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
double df_hydset(double kinematic_viscosity, double known_velocity, double wall_distance, double friction_velocity_guess, double roughness_height)
Implementation of df_hydset().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nu_t()

double nu_t ( double  yplus)

Computes turbulent eddy viscosity ratio (ν_t / ν)

Uses the mixing length model with van Driest damping: ν_t / ν = κ * y+ * [1 - exp(-y+ / A+)]² where A+ ≈ 19 is the damping coefficient.

PHYSICAL INTERPRETATION:

  • Near wall (y+ → 0): ν_t → 0 (viscous effects dominate)
  • Far from wall (y+ >> A+): ν_t ~ κ * y+ (mixing length theory)
  • Damping function smoothly transitions between these limits
Parameters
[in]yplusNormalized wall distance y+ = y * u_τ / ν
Returns
Eddy viscosity ratio ν_t / ν
Note
This is the standard mixing length model with van Driest damping
Valid in the inner layer (y+ < 50-100)

Computes turbulent eddy viscosity ratio (ν_t / ν)

Local to this translation unit.

Definition at line 303 of file wallfunction.c.

304{
305 // van Driest damping function: [1 - exp(-y+ / A+)]²
306 double damping_function = 1.0 - exp(-yplus / DAMPING_COEFFICIENT);
307
308 // Mixing length model: ν_t / ν = κ * y+ * D²
309 return KAPPA * yplus * damping_function * damping_function;
310}
#define DAMPING_COEFFICIENT
Eddy viscosity damping coefficient (van Driest damping)
Here is the caller graph for this function:

◆ integrate_1()

double integrate_1 ( double  kinematic_viscosity,
double  wall_distance,
double  friction_velocity,
int  integration_mode 
)

Integrates eddy viscosity profile from wall to distance y.

Computes integrals needed for non-equilibrium wall functions: If mode=0: ∫[0 to y] dy / (ν + ν_t) If mode=1: ∫[0 to y] y dy / (ν + ν_t)

These integrals appear in the solution of the momentum equation with pressure gradients in the near-wall region.

NUMERICAL METHOD:

  • Trapezoidal rule with 30 integration points
  • Higher-order correction at endpoints for accuracy
Parameters
[in]kinematic_viscosityKinematic viscosity ν
[in]wall_distanceDistance from wall y
[in]friction_velocityFriction velocity u_τ
[in]integration_mode0 for F integral, 1 for Fy integral
Returns
Value of the integral
Note
Used in Cabot wall function for pressure gradient effects

Integrates eddy viscosity profile from wall to distance y.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
integrate_1()

Definition at line 318 of file wallfunction.c.

320{
321 const int num_points = 30;
322 double step_size = wall_distance / (num_points - 1);
323 double integral_values[num_points];
324
325 // Compute integrand at each point
326 for (int i = 0; i < num_points; i++) {
327 double current_distance = i * step_size;
328 double yplus = current_distance * friction_velocity / kinematic_viscosity;
329 double eddy_viscosity_ratio = nu_t(yplus);
330
331 if (integration_mode == 0) {
332 // Mode 0: integrand = 1 / [(1 + ν_t/ν) * ν]
333 integral_values[i] = 1.0 / ((1.0 + eddy_viscosity_ratio) * kinematic_viscosity);
334 }
335 else {
336 // Mode 1: integrand = y / [(1 + ν_t/ν) * ν]
337 integral_values[i] = current_distance /
338 ((1.0 + eddy_viscosity_ratio) * kinematic_viscosity);
339 }
340 }
341
342 // Trapezoidal rule integration with corrected endpoints
343 double integral_sum = 0.0;
344
345 // Interior points: weight = (f[i-1] + 2*f[i] + f[i+1]) * dy/4
346 for (int i = 1; i < num_points - 1; i++) {
347 integral_sum += (integral_values[i-1] + 2.0 * integral_values[i] +
348 integral_values[i+1]) * 0.25 * step_size;
349 }
350
351 // Endpoint correction for higher accuracy
352 integral_sum += 0.1667 * step_size *
353 (2.0 * integral_values[0] + integral_values[1] +
354 2.0 * integral_values[num_points-1] + integral_values[num_points-2]);
355
356 return integral_sum;
357}
double nu_t(double yplus)
Internal helper implementation: nu_t().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ taw()

double taw ( double  kinematic_viscosity,
double  friction_velocity,
double  wall_distance,
double  velocity,
double  pressure_gradient_tangent 
)

Computes wall shear stress with pressure gradient effects.

Solves the integrated momentum equation in the near-wall region: τ_w = (u - dp/dx * F_y) / F_1 where F_1 and F_y are integrals of the effective viscosity profile.

This accounts for non-equilibrium effects due to streamwise pressure gradients.

Parameters
[in]kinematic_viscosityKinematic viscosity
[in]friction_velocityFriction velocity u_τ
[in]wall_distanceDistance from wall
[in]velocityVelocity at wall_distance
[in]pressure_gradient_tangentTangential pressure gradient dp/ds
Returns
Wall shear stress τ_w
Note
This is more accurate than equilibrium wall functions in separated flows

Computes wall shear stress with pressure gradient effects.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
taw()

Definition at line 369 of file wallfunction.c.

371{
372 // Compute integrated viscosity profiles
373 double F1 = integrate_1(kinematic_viscosity, wall_distance, friction_velocity, 0);
374 double Fy = integrate_1(kinematic_viscosity, wall_distance, friction_velocity, 1);
375
376 // Apply momentum balance: τ_w * F1 = u - (dp/dx) * Fy
377 return (1.0 / F1) * (velocity - pressure_gradient_tangent * Fy);
378}
double integrate_1(double kinematic_viscosity, double wall_distance, double friction_velocity, int integration_mode)
Implementation of integrate_1().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ u_Cabot()

double u_Cabot ( double  kinematic_viscosity,
double  wall_distance,
double  friction_velocity,
double  pressure_gradient_tangent,
double  wall_shear_stress 
)

Computes velocity using Cabot wall function.

Reconstructs velocity from wall shear stress and pressure gradient: u = τ_w * F1 + (dp/dx) * Fy

Parameters
[in]kinematic_viscosityKinematic viscosity
[in]wall_distanceDistance from wall
[in]friction_velocityFriction velocity
[in]pressure_gradient_tangentTangential pressure gradient
[in]wall_shear_stressWall shear stress
Returns
Velocity at wall_distance

Computes velocity using Cabot wall function.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
u_Cabot()

Definition at line 386 of file wallfunction.c.

389{
390 double F1 = integrate_1(kinematic_viscosity, wall_distance, friction_velocity, 0);
391 double Fy = integrate_1(kinematic_viscosity, wall_distance, friction_velocity, 1);
392
393 return wall_shear_stress * F1 + pressure_gradient_tangent * Fy;
394}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ f_Cabot()

double f_Cabot ( double  kinematic_viscosity,
double  velocity,
double  wall_distance,
double  friction_velocity_guess,
double  pressure_gradient_tangent,
double  pressure_gradient_normal 
)

Residual function for Cabot wall function.

Computes: f(u_τ) = u_τ - sqrt(|τ_w(u_τ)|) This enforces consistency between u_τ and τ_w.

Parameters
[in]kinematic_viscosityKinematic viscosity
[in]velocityVelocity
[in]wall_distanceDistance from wall
[in]friction_velocity_guessGuess for u_τ
[in]pressure_gradient_tangentTangential pressure gradient
[in]pressure_gradient_normalNormal pressure gradient (currently unused)
Returns
Residual value

Residual function for Cabot wall function.

Local to this translation unit.

Definition at line 400 of file wallfunction.c.

403{
404 (void)pressure_gradient_normal;
405 double wall_shear = taw(kinematic_viscosity, friction_velocity_guess,
406 wall_distance, velocity, pressure_gradient_tangent);
407
408 return friction_velocity_guess - sqrt(fabs(wall_shear));
409}
double taw(double kinematic_viscosity, double friction_velocity, double wall_distance, double velocity, double pressure_gradient_tangent)
Implementation of taw().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ df_Cabot()

double df_Cabot ( double  kinematic_viscosity,
double  velocity,
double  wall_distance,
double  friction_velocity_guess,
double  pressure_gradient_tangent,
double  pressure_gradient_normal 
)

Numerical derivative for Cabot wall function.

Parameters
kinematic_viscosityFluid kinematic viscosity.
velocityResolved tangential velocity at the wall-model point.
wall_distanceNormal distance from the wall.
friction_velocity_guessCurrent friction-velocity iterate.
pressure_gradient_tangentTangential pressure-gradient contribution.
pressure_gradient_normalNormal pressure-gradient contribution.
Returns
Derivative of the Cabot residual with respect to friction velocity.

Numerical derivative for Cabot wall function.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
df_Cabot()

Definition at line 417 of file wallfunction.c.

420{
421 const double perturbation = 1.e-7;
422
423 double f_plus = f_Cabot(kinematic_viscosity, velocity, wall_distance,
424 friction_velocity_guess + perturbation,
425 pressure_gradient_tangent, pressure_gradient_normal);
426
427 double f_minus = f_Cabot(kinematic_viscosity, velocity, wall_distance,
428 friction_velocity_guess - perturbation,
429 pressure_gradient_tangent, pressure_gradient_normal);
430
431 return (f_plus - f_minus) / (2.0 * perturbation);
432}
double f_Cabot(double kinematic_viscosity, double velocity, double wall_distance, double friction_velocity_guess, double pressure_gradient_tangent, double pressure_gradient_normal)
Internal helper implementation: f_Cabot().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_utau_Cabot()

void find_utau_Cabot ( double  kinematic_viscosity,
double  velocity,
double  wall_distance,
double  initial_guess,
double  pressure_gradient_tangent,
double  pressure_gradient_normal,
double *  friction_velocity,
double *  wall_shear_velocity,
double *  wall_shear_normal 
)

Solves for friction velocity using Cabot wall function.

This non-equilibrium wall function accounts for pressure gradient effects, making it more accurate in separated or strongly accelerating/decelerating flows.

Parameters
[in]kinematic_viscosityKinematic viscosity
[in]velocityVelocity at reference point
[in]wall_distanceDistance from wall
[in]initial_guessInitial guess for u_τ
[in]pressure_gradient_tangentTangential pressure gradient
[in]pressure_gradient_normalNormal pressure gradient
[out]friction_velocityConverged friction velocity
[out]wall_shear_velocityWall shear stress for velocity
[out]wall_shear_normalWall shear stress for normal pressure gradient

Solves for friction velocity using Cabot wall function.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
find_utau_Cabot()

Definition at line 440 of file wallfunction.c.

444{
445 double current_guess = initial_guess;
446 double new_guess;
447
448 const int max_iterations = 30;
449 const double convergence_tolerance = 1.e-10;
450
451 int iteration;
452 for (iteration = 0; iteration < max_iterations; iteration++) {
453 double residual = f_Cabot(kinematic_viscosity, velocity, wall_distance,
454 current_guess, pressure_gradient_tangent,
455 pressure_gradient_normal);
456
457 double derivative = df_Cabot(kinematic_viscosity, velocity, wall_distance,
458 current_guess, pressure_gradient_tangent,
459 pressure_gradient_normal);
460
461 new_guess = fabs(current_guess - residual / derivative);
462
463 if (fabs(current_guess - new_guess) < convergence_tolerance) {
464 break;
465 }
466
467 current_guess = new_guess;
468 }
469
470 if (fabs(current_guess - new_guess) > 1.e-5 && iteration >= 29) {
472 "Cabot wall-function iteration reached its limit without the requested tolerance.\n");
473 }
474
475 *friction_velocity = new_guess;
476 *wall_shear_velocity = taw(kinematic_viscosity, new_guess, wall_distance,
477 velocity, pressure_gradient_tangent);
478 *wall_shear_normal = taw(kinematic_viscosity, new_guess, wall_distance,
479 0.0, pressure_gradient_normal);
480}
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30
double df_Cabot(double kinematic_viscosity, double velocity, double wall_distance, double friction_velocity_guess, double pressure_gradient_tangent, double pressure_gradient_normal)
Implementation of df_Cabot().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ u_Werner()

double u_Werner ( double  kinematic_viscosity,
double  wall_distance,
double  friction_velocity 
)

Computes velocity using Werner-Wengle wall function.

The pointwise Werner-Wengle profile, and the relation the solver uses: the wall function evaluates it at the boundary cell with the friction velocity that find_utau_Werner() takes from the reference cell. Explicit relation: u+ = y+ for y+ < 11.81 (viscous sublayer) u+ = A * (y+)^B for y+ ≥ 11.81 (power law) where A = 8.3, B = 1/7 are empirical constants.

ADVANTAGES:

  • Explicit (no iteration required)
  • Computationally cheap
  • Reasonable accuracy for equilibrium boundary layers

LIMITATIONS:

  • Less accurate than log-law for high Reynolds numbers
  • No pressure gradient effects
Parameters
[in]kinematic_viscosityKinematic viscosity
[in]wall_distanceDistance from wall
[in]friction_velocityFriction velocity
Returns
Tangential velocity

Computes velocity using Werner-Wengle wall function.

Local to this translation unit.

Definition at line 490 of file wallfunction.c.

492{
493 /* The pointwise profile, and the production path: `wall_function()` evaluates it at
494 the boundary cell with the friction velocity `find_utau_Werner()` takes from the
495 reference cell, so one relation is used in both directions. */
496 double yplus = friction_velocity * wall_distance / kinematic_viscosity;
497
498 // Werner-Wengle constants
499 const double power_law_coefficient = 8.3;
500 const double power_law_exponent = 1.0 / 7.0;
501
502 double velocity;
503
504 if (yplus <= VISCOUS_SUBLAYER_YPLUS) {
505 // Viscous sublayer: u+ = y+
506 velocity = yplus * friction_velocity;
507 }
508 else {
509 // Power-law region: u+ = A * (y+)^B
510 velocity = power_law_coefficient * pow(yplus, power_law_exponent) * friction_velocity;
511 }
512
513 return velocity;
514}
Here is the caller graph for this function:

◆ taw_Werner()

double taw_Werner ( double  kinematic_viscosity,
double  velocity,
double  wall_distance 
)

Wall shear stress from the cell-integrated Werner-Wengle relation.

Note
Not wired into the solver. The profile is assumed to hold across a cell of height wall_distance and integrated, so velocity must be the AVERAGE over [0, wall_distance] - a finite-volume first-cell value with its full height. The wall function's reference is instead a point value at the second cell's centre; read as an average it over-predicts u_tau by about (1 + B)^(1/(1+B)), 12-14% on a wall-modelled channel at Re_tau ~ 1000. The solver uses the pointwise pair find_utau_Werner() / u_Werner(), which is also closed form. Kept, with its inverse u_Werner_explicit(), for a caller that does supply a cell average.

|u| <= u_m : tau_w = 2 nu |u| / y |u| > u_m : tau_w = [ (1-B)/2 A^((1+B)/(1-B)) (nu/y)^(1+B)

  • (1+B)/A (nu/y)^B |u| ]^(2/(1+B))

with A = 8.3, B = 1/7, and the switch at u_m = nu/(2y) A^(2/(1-B)). That threshold depends only on the geometry and the fluid, which is what makes the inversion explicit; a threshold written in terms of the friction velocity would reintroduce the iteration the model exists to avoid. The two branches meet exactly at u_m.

Pairs with u_Werner_explicit(), which inverts it. Do not pair it with u_Werner(), which is the pointwise profile rather than its cell integral.

Parameters
[in]kinematic_viscosityKinematic viscosity.
[in]velocityWall-parallel speed at wall_distance, sign ignored.
[in]wall_distanceNormal distance the profile is integrated over.
Returns
Wall shear stress, equal to the square of the friction velocity.

Wall shear stress from the cell-integrated Werner-Wengle relation.

Full API contract is documented with the header declaration in include/wallfunction.h.

Definition at line 523 of file wallfunction.c.

524{
525 const double A = 8.3;
526 const double B = 1.0 / 7.0;
527 const double speed = fabs(velocity);
528 const double nu_over_y = kinematic_viscosity / wall_distance;
529
530 /* The switch is written in terms of the geometry alone. Expressing it through the
531 friction velocity, as the iterative residual does, makes the branch depend on the
532 answer and forces a Newton solve the closed form does not need. */
533 const double transition_speed = 0.5 * nu_over_y * pow(A, 2.0 / (1.0 - B));
534
535 if (speed <= transition_speed) {
536 /* Integrating u+ = y+ across the cell leaves the factor of two that separates
537 this from the pointwise relation tau_w = nu u / y. */
538 return 2.0 * kinematic_viscosity * speed / wall_distance;
539 }
540
541 {
542 const double term1 = 0.5 * (1.0 - B) * pow(A, (1.0 + B) / (1.0 - B)) *
543 pow(nu_over_y, 1.0 + B);
544 const double term2 = (1.0 + B) / A * pow(nu_over_y, B) * speed;
545
546 return pow(term1 + term2, 2.0 / (1.0 + B));
547 }
548}
Here is the caller graph for this function:

◆ u_Werner_explicit()

double u_Werner_explicit ( double  kinematic_viscosity,
double  wall_distance,
double  wall_shear_stress 
)

Wall-parallel velocity at a distance, from the Werner-Wengle wall stress.

The exact inverse of taw_Werner(), branch for branch, so that a stress obtained from a velocity at one distance reproduces a consistent velocity at another. It is monotonically increasing in wall_distance, so a cell nearer the wall than the one the stress came from is always assigned the slower speed.

The branch is selected on the stress rather than the velocity it is about to produce, using the same threshold expressed as tau_m = (nu/y)^2 A^(2/(1-B)).

Parameters
[in]kinematic_viscosityKinematic viscosity.
[in]wall_distanceNormal distance to evaluate at.
[in]wall_shear_stressWall shear stress from taw_Werner().
Returns
Wall-parallel speed at wall_distance, non-negative.

Wall-parallel velocity at a distance, from the Werner-Wengle wall stress.

Full API contract is documented with the header declaration in include/wallfunction.h.

Definition at line 557 of file wallfunction.c.

559{
560 const double A = 8.3;
561 const double B = 1.0 / 7.0;
562 const double stress = fabs(wall_shear_stress);
563 const double nu_over_y = kinematic_viscosity / wall_distance;
564
565 /* The same threshold as taw_Werner(), carried over to the stress side. The two
566 branches meet here exactly, so selecting on the stress cannot land on the wrong
567 side of the velocity switch. */
568 const double transition_stress = nu_over_y * nu_over_y * pow(A, 2.0 / (1.0 - B));
569
570 if (stress <= transition_stress) {
571 return stress * wall_distance / (2.0 * kinematic_viscosity);
572 }
573
574 {
575 const double offset = 0.5 * (1.0 - B) * pow(A, (1.0 + B) / (1.0 - B)) *
576 pow(nu_over_y, 1.0 + B);
577 /* Non-negative by construction above the threshold - it is zero only in the
578 limit of the switch - so the max guards roundoff, not a modelling case. */
579 const double bracket = PetscMax(pow(stress, 0.5 * (1.0 + B)) - offset, 0.0);
580
581 return A / (1.0 + B) * pow(1.0 / nu_over_y, B) * bracket;
582 }
583}
Here is the caller graph for this function:

◆ find_utau_Werner()

double find_utau_Werner ( double  kinematic_viscosity,
double  velocity,
double  wall_distance,
double  initial_guess 
)

Friction velocity from a point velocity, inverting u_Werner() exactly.

The closed-form inverse of the pointwise Werner-Wengle profile, branch for branch, and the solver's path. Along that profile U y / nu = (y+)^2 in the sublayer, so the branch is chosen from the data alone - sublayer while U y / nu <= 11.81^2 - and each branch inverts explicitly:

sublayer : u_tau = sqrt(nu |U| / y) power law : u_tau = ( |U| / (A (y/nu)^B) )^(1/(1+B)), A = 8.3, B = 1/7

No iteration, so the residual it feeds stays smooth for a matrix-free Jacobian.

Parameters
[in]kinematic_viscosityKinematic viscosity
[in]velocityWall-parallel speed at the reference point, sign ignored
[in]wall_distanceDistance from the wall to that point
[in]initial_guessUnused; kept so existing callers need no change
Returns
Friction velocity

Friction velocity from a point velocity, inverting u_Werner() exactly.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
find_utau_Werner()

Definition at line 591 of file wallfunction.c.

593{
594 const double A = 8.3;
595 const double B = 1.0 / 7.0;
596 const double speed = fabs(velocity);
597 const double y_over_nu = wall_distance / kinematic_viscosity;
598 (void)initial_guess;
599
600 /* The exact inverse of `u_Werner()`, branch for branch. Along that profile
601 U y / nu = (y+)^2 in the sublayer, so the branch it was evaluated on is decided by
602 the data alone: the sublayer holds while U y / nu <= VISCOUS_SUBLAYER_YPLUS^2, the
603 same switch `u_Werner()` applies to y+. Both branches then invert explicitly. */
604 if (speed * y_over_nu <= VISCOUS_SUBLAYER_YPLUS * VISCOUS_SUBLAYER_YPLUS) {
605 return sqrt(speed / y_over_nu); /* U = u_tau^2 y / nu */
606 }
607 return pow(speed / (A * pow(y_over_nu, B)), 1.0 / (1.0 + B)); /* U = A u_tau^(1+B) (y/nu)^B */
608}
Here is the caller graph for this function:

◆ u_loglaw()

double u_loglaw ( double  wall_distance,
double  friction_velocity,
double  roughness_length 
)

Computes velocity using simple log-law (smooth wall with roughness offset)

Simple logarithmic profile: u = (u_τ / κ) * ln((y + y0) / y0) where y0 is a roughness length scale.

Parameters
[in]wall_distanceDistance from wall
[in]friction_velocityFriction velocity
[in]roughness_lengthRoughness length scale y0
Returns
Velocity
Note
This is a simplified model; use u_hydset_roughness for better accuracy

Computes velocity using simple log-law (smooth wall with roughness offset)

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
u_loglaw()

Definition at line 620 of file wallfunction.c.

621{
622 return friction_velocity * (1.0 / KAPPA) * log((roughness_length + wall_distance) / roughness_length);
623}
Here is the caller graph for this function:

◆ find_utau_loglaw()

double find_utau_loglaw ( double  velocity,
double  wall_distance,
double  roughness_length 
)

Solves for friction velocity using simple log-law (explicit formula)

Explicit inversion: u_τ = κ * u / ln((y + y0) / y0)

Parameters
[in]velocityKnown velocity
[in]wall_distanceDistance from wall
[in]roughness_lengthRoughness length scale
Returns
Friction velocity

Solves for friction velocity using simple log-law (explicit formula)

Local to this translation unit.

Definition at line 629 of file wallfunction.c.

630{
631 return KAPPA * velocity / log((wall_distance + roughness_length) / roughness_length);
632}
Here is the caller graph for this function:

◆ wall_function()

void wall_function ( UserCtx *  user,
double  distance_reference,
double  distance_boundary,
Cmpnts  velocity_wall,
Cmpnts  velocity_reference,
Cmpnts *  velocity_boundary,
PetscReal *  friction_velocity,
double  normal_x,
double  normal_y,
double  normal_z 
)

Applies standard wall function with Werner-Wengle model.

This is a high-level interface that:

  1. Decomposes velocity into normal/tangential components
  2. Applies wall function to tangential velocity
  3. Interpolates normal velocity
  4. Reconstructs total velocity
Parameters
[in]userSimulation context
[in]distance_referenceDistance to reference point
[in]distance_boundaryDistance to boundary point
[in]velocity_wallWall velocity
[in]velocity_referenceReference velocity
[out]velocity_boundaryOutput boundary velocity
[out]friction_velocityOutput friction velocity
[in]normal_xX-component of wall normal
[in]normal_yY-component of wall normal
[in]normal_zZ-component of wall normal

Applies standard wall function with Werner-Wengle model.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/wallfunction.h.

See also
wall_function()

Definition at line 648 of file wallfunction.c.

652{
653 SimCtx *simCtx = user->simCtx;
654 double kinematic_viscosity = 1.0 / simCtx->ren;
655
656 // Decompose velocity into components
657 double delta_u = velocity_reference.x - velocity_wall.x;
658 double delta_v = velocity_reference.y - velocity_wall.y;
659 double delta_w = velocity_reference.z - velocity_wall.z;
660
661 double normal_velocity = delta_u * normal_x + delta_v * normal_y + delta_w * normal_z;
662
663 double tangential_u = delta_u - normal_velocity * normal_x;
664 double tangential_v = delta_v - normal_velocity * normal_y;
665 double tangential_w = delta_w - normal_velocity * normal_z;
666
667 double tangential_magnitude = sqrt(tangential_u * tangential_u +
668 tangential_v * tangential_v +
669 tangential_w * tangential_w);
670
671 /* The reference speed is a point value - the velocity at the reference cell's centre,
672 `distance_reference` from the wall - so the wall stress comes from the pointwise
673 Werner-Wengle profile inverted there, and the boundary cell's speed from that same
674 profile at its own centre. One relation in both directions, as the log-law path
675 does, and both directions are closed form, so there is still no inner iteration.
676 The cell-integral relation (`taw_Werner()`) reads its input as the average over
677 [0, distance_reference]; given this point value it over-predicted u_tau by about
678 (1 + 1/7)^(7/8), 12-14%, on a wall-modelled channel at Re_tau ~ 1000. */
679 const double friction = find_utau_Werner(kinematic_viscosity, tangential_magnitude,
680 distance_reference, 0.0);
681 double tangential_modeled = u_Werner(kinematic_viscosity, distance_boundary, friction);
682 if (friction_velocity) {
683 *friction_velocity = (PetscReal)friction;
684 }
685
686 // Scale tangential components
687 if (tangential_magnitude > 1.e-10) {
688 tangential_u *= tangential_modeled / tangential_magnitude;
689 tangential_v *= tangential_modeled / tangential_magnitude;
690 tangential_w *= tangential_modeled / tangential_magnitude;
691 }
692 else {
693 tangential_u = tangential_v = tangential_w = 0.0;
694 }
695
696 // Reconstruct velocity: U = U_t + U_n * n
697 (*velocity_boundary).x = tangential_u + (distance_boundary / distance_reference) * normal_velocity * normal_x;
698 (*velocity_boundary).y = tangential_v + (distance_boundary / distance_reference) * normal_velocity * normal_y;
699 (*velocity_boundary).z = tangential_w + (distance_boundary / distance_reference) * normal_velocity * normal_z;
700
701 // Add wall velocity
702 (*velocity_boundary).x += velocity_wall.x;
703 (*velocity_boundary).y += velocity_wall.y;
704 (*velocity_boundary).z += velocity_wall.z;
705}
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:1077
PetscReal ren
Definition variables.h:906
The master context for the entire simulation.
Definition variables.h:859
double u_Werner(double kinematic_viscosity, double wall_distance, double friction_velocity)
Internal helper implementation: u_Werner().
double find_utau_Werner(double kinematic_viscosity, double velocity, double wall_distance, double initial_guess)
Implementation of find_utau_Werner().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ wall_function_loglaw()

void wall_function_loglaw ( UserCtx *  user,
double  roughness_height,
double  distance_reference,
double  distance_boundary,
Cmpnts  velocity_wall,
Cmpnts  velocity_reference,
Cmpnts *  velocity_boundary,
PetscReal *  friction_velocity,
double  normal_x,
double  normal_y,
double  normal_z 
)

Applies log-law wall function with roughness correction.

This is the recommended wall function interface for most applications. It uses the roughness-corrected log-law which is accurate for both smooth and rough walls.

Parameters
[in]userSimulation context
[in]roughness_heightWall roughness height ks
[in]distance_referenceDistance to reference point
[in]distance_boundaryDistance to boundary point
[in]velocity_wallWall velocity (typically zero)
[in]velocity_referenceReference velocity
[out]velocity_boundaryOutput boundary velocity
[out]friction_velocityOutput friction velocity u_τ
[in]normal_xX-component of wall normal
[in]normal_yY-component of wall normal
[in]normal_zZ-component of wall normal
Note
Sets velocity to reference value if y+ > 300 (outside log-layer)

Applies log-law wall function with roughness correction.

Local to this translation unit.

Definition at line 711 of file wallfunction.c.

716{
717 SimCtx *simCtx = user->simCtx;
718 double kinematic_viscosity = 1.0 / simCtx->ren;
719
720 // Decompose velocity
721 double delta_u = velocity_reference.x - velocity_wall.x;
722 double delta_v = velocity_reference.y - velocity_wall.y;
723 double delta_w = velocity_reference.z - velocity_wall.z;
724
725 double normal_velocity = delta_u * normal_x + delta_v * normal_y + delta_w * normal_z;
726
727 double tangential_u = delta_u - normal_velocity * normal_x;
728 double tangential_v = delta_v - normal_velocity * normal_y;
729 double tangential_w = delta_w - normal_velocity * normal_z;
730
731 double tangential_magnitude = sqrt(tangential_u * tangential_u +
732 tangential_v * tangential_v +
733 tangential_w * tangential_w);
734
735 // Solve for friction velocity
736 *friction_velocity = find_utau_hydset(kinematic_viscosity, tangential_magnitude,
737 distance_reference, 0.001, roughness_height);
738
739 // Compute wall function velocity
740 double tangential_modeled = u_hydset_roughness(kinematic_viscosity, distance_boundary,
741 *friction_velocity, roughness_height);
742
743 // Check if outside valid range (y+ > 300)
744 if (tangential_modeled < 0.0) {
745 tangential_modeled = tangential_magnitude;
746 }
747
748 // Scale tangential components
749 if (tangential_magnitude > 1.e-10) {
750 tangential_u *= tangential_modeled / tangential_magnitude;
751 tangential_v *= tangential_modeled / tangential_magnitude;
752 tangential_w *= tangential_modeled / tangential_magnitude;
753 }
754 else {
755 tangential_u = tangential_v = tangential_w = 0.0;
756 }
757
758 // Reconstruct total velocity
759 (*velocity_boundary).x = tangential_u + (distance_boundary / distance_reference) * normal_velocity * normal_x;
760 (*velocity_boundary).y = tangential_v + (distance_boundary / distance_reference) * normal_velocity * normal_y;
761 (*velocity_boundary).z = tangential_w + (distance_boundary / distance_reference) * normal_velocity * normal_z;
762
763 // Add wall velocity
764 (*velocity_boundary).x += velocity_wall.x;
765 (*velocity_boundary).y += velocity_wall.y;
766 (*velocity_boundary).z += velocity_wall.z;
767}
double u_hydset_roughness(double kinematic_viscosity, double wall_distance, double friction_velocity, double roughness_height)
Internal helper implementation: u_hydset_roughness().
double find_utau_hydset(double kinematic_viscosity, double known_velocity, double wall_distance, double initial_guess, double roughness_height)
Implementation of find_utau_hydset().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ wall_function_Cabot()

void wall_function_Cabot ( UserCtx *  user,
double  roughness_height,
double  distance_reference,
double  distance_boundary,
Cmpnts  velocity_wall,
Cmpnts  velocity_reference,
Cmpnts *  velocity_boundary,
PetscReal *  friction_velocity,
double  normal_x,
double  normal_y,
double  normal_z,
double  pressure_gradient_x,
double  pressure_gradient_y,
double  pressure_gradient_z,
int  iteration_count 
)

Applies Cabot non-equilibrium wall function with pressure gradients.

This wall function accounts for pressure gradient effects and is most accurate in separated or strongly accelerating/decelerating flows.

Parameters
[in]userSimulation context
[in]roughness_heightWall roughness (currently unused in this version)
[in]distance_referenceDistance to reference point
[in]distance_boundaryDistance to boundary point
[in]velocity_wallWall velocity
[in]velocity_referenceReference velocity
[out]velocity_boundaryOutput boundary velocity
[out]friction_velocityOutput friction velocity
[in]normal_xX-component of wall normal
[in]normal_yY-component of wall normal
[in]normal_zZ-component of wall normal
[in]pressure_gradient_xX-component of pressure gradient
[in]pressure_gradient_yY-component of pressure gradient
[in]pressure_gradient_zZ-component of pressure gradient
[in]iteration_countCurrent iteration count
Note
Only updates friction velocity every 5 iterations for stability
Normal pressure gradient currently set to zero

Applies Cabot non-equilibrium wall function with pressure gradients.

Local to this translation unit.

Definition at line 773 of file wallfunction.c.

780{
781 (void)roughness_height;
782 SimCtx *simCtx = user->simCtx;
783 double kinematic_viscosity = 1.0 / simCtx->ren;
784
785 // Decompose velocity
786 double delta_u = velocity_reference.x - velocity_wall.x;
787 double delta_v = velocity_reference.y - velocity_wall.y;
788 double delta_w = velocity_reference.z - velocity_wall.z;
789
790 double normal_velocity = delta_u * normal_x + delta_v * normal_y + delta_w * normal_z;
791
792 double tangential_u = delta_u - normal_velocity * normal_x;
793 double tangential_v = delta_v - normal_velocity * normal_y;
794 double tangential_w = delta_w - normal_velocity * normal_z;
795
796 double tangential_magnitude = sqrt(tangential_u * tangential_u +
797 tangential_v * tangential_v +
798 tangential_w * tangential_w);
799
800 // Compute tangential pressure gradient
801 double pressure_gradient_tangent = 0.0;
802 if (tangential_magnitude > 1.e-10) {
803 pressure_gradient_tangent = (pressure_gradient_x * tangential_u +
804 pressure_gradient_y * tangential_v +
805 pressure_gradient_z * tangential_w) / tangential_magnitude;
806 }
807
808 // Normal pressure gradient (currently set to zero)
809 double pressure_gradient_normal = 0.0;
810
811 // Solve for friction velocity (only on first iteration or periodically)
812 if (iteration_count == 0 || iteration_count > 4) {
813 double utau, wall_shear1, wall_shear2;
814 find_utau_Cabot(kinematic_viscosity, tangential_magnitude, distance_reference,
815 0.01, pressure_gradient_tangent, pressure_gradient_normal,
816 &utau, &wall_shear1, &wall_shear2);
817 *friction_velocity = utau;
818 }
819
820 // Compute wall function velocity with pressure gradient correction
821 double tangential_modeled = u_Cabot(kinematic_viscosity, distance_boundary,
822 *friction_velocity, pressure_gradient_tangent,
823 taw(kinematic_viscosity, *friction_velocity,
824 distance_reference, tangential_magnitude,
825 pressure_gradient_tangent));
826
827 // Scale tangential components
828 if (tangential_magnitude > 1.e-10) {
829 tangential_u *= tangential_modeled / tangential_magnitude;
830 tangential_v *= tangential_modeled / tangential_magnitude;
831 tangential_w *= tangential_modeled / tangential_magnitude;
832 }
833 else {
834 tangential_u = tangential_v = tangential_w = 0.0;
835 }
836
837 // Reconstruct total velocity
838 (*velocity_boundary).x = tangential_u + (distance_boundary / distance_reference) * normal_velocity * normal_x;
839 (*velocity_boundary).y = tangential_v + (distance_boundary / distance_reference) * normal_velocity * normal_y;
840 (*velocity_boundary).z = tangential_w + (distance_boundary / distance_reference) * normal_velocity * normal_z;
841
842 // Add wall velocity
843 (*velocity_boundary).x += velocity_wall.x;
844 (*velocity_boundary).y += velocity_wall.y;
845 (*velocity_boundary).z += velocity_wall.z;
846}
double u_Cabot(double kinematic_viscosity, double wall_distance, double friction_velocity, double pressure_gradient_tangent, double wall_shear_stress)
Implementation of u_Cabot().
void find_utau_Cabot(double kinematic_viscosity, double velocity, double wall_distance, double initial_guess, double pressure_gradient_tangent, double pressure_gradient_normal, double *friction_velocity, double *wall_shear_velocity, double *wall_shear_normal)
Implementation of find_utau_Cabot().
Here is the call graph for this function:
Here is the caller graph for this function: