Program Listing for File stress.h¶
↰ Return to documentation for file (source/relations/stress.h
)
/*
* stress.h Atmospheric Boundary Layer Reynolds Stress relations
*
* Author: Tom Clark (thclark @ github)
*
* Copyright (c) 2019 Octue Ltd. All Rights Reserved.
*
*/
#ifndef ES_FLOW_STRESS_H_
#define ES_FLOW_STRESS_H_
#include <Eigen/Dense>
#include <Eigen/Core>
#include <iostream>
#include <iomanip>
#include <math.h>
#include "NumericalIntegration.h"
#include "profile.h"
#include "relations/velocity.h"
#include "utilities/integration.h"
#include "definitions.h"
#include "cpplot.h"
using namespace utilities;
using namespace cpplot;
namespace es {
template<typename T_scalar, typename T_param>
class DeficitFunctor {
private:
double m_kappa, m_shear_ratio;
T_param m_pi_coles;
bool m_lewkowicz, m_deficit_squared;
public:
DeficitFunctor(const double kappa, const T_param pi_coles, const double shear_ratio, const bool lewkowicz, const bool deficit_squared=false) : m_kappa(kappa), m_pi_coles(pi_coles), m_shear_ratio(shear_ratio), m_lewkowicz(lewkowicz), m_deficit_squared(deficit_squared) {};
T_scalar operator() (T_scalar eta) const{
if (m_deficit_squared){
return pow(deficit(eta, m_kappa, m_pi_coles, m_shear_ratio, m_lewkowicz), 2.0);
}
return deficit(eta, m_kappa, m_pi_coles, m_shear_ratio, m_lewkowicz);
};
};
void reynolds_stress_13(Eigen::ArrayXd &r13_a, Eigen::ArrayXd &r13_b, const double beta, const Eigen::ArrayXd &eta, const double kappa, const double pi_coles, const double shear_ratio, const double zeta){
// Check the input has a valid range; the integration will be messed up otherwise.
if ((eta(eta.rows()-1) != 1.0) || (eta(0) != 0.0)) {
throw std::invalid_argument("Input eta must be defined in the range 0, 1 exactly");
}
// TODO Improved control of models - see #61.
bool lewkowicz = true;
// Get f between eta = 0 and eta = 1
Eigen::ArrayXd f = deficit(eta, kappa, pi_coles, shear_ratio, lewkowicz);
const double d_pi = 0.001 * pi_coles;
// Do the integrations for ei, with central differencing for numerical differentiation of e coefficients 5-7
DeficitFunctor<double, double> deficit_functor(KAPPA_VON_KARMAN, pi_coles, shear_ratio, true, false);
DeficitFunctor<double, double> deficit_functor_plus(KAPPA_VON_KARMAN, pi_coles+d_pi, shear_ratio, true, false);
DeficitFunctor<double, double> deficit_functor_minus(KAPPA_VON_KARMAN, pi_coles-d_pi, shear_ratio, true, false);
DeficitFunctor<double, double> deficit_squared_functor(KAPPA_VON_KARMAN, pi_coles, shear_ratio, true, true);
DeficitFunctor<double, double> deficit_squared_functor_plus(KAPPA_VON_KARMAN, pi_coles+d_pi, shear_ratio, true, true);
DeficitFunctor<double, double> deficit_squared_functor_minus(KAPPA_VON_KARMAN, pi_coles-d_pi, shear_ratio, true, true);
Eigen::ArrayXd e1 = utilities::cumulative_integrate(eta, deficit_functor);
Eigen::ArrayXd e1_plus = utilities::cumulative_integrate(eta, deficit_functor_plus);
Eigen::ArrayXd e1_minus = utilities::cumulative_integrate(eta, deficit_functor_minus);
Eigen::ArrayXd e2 = utilities::cumulative_integrate(eta, deficit_squared_functor);
Eigen::ArrayXd e2_plus = utilities::cumulative_integrate(eta, deficit_squared_functor_plus);
Eigen::ArrayXd e2_minus = utilities::cumulative_integrate(eta, deficit_squared_functor_minus);
Eigen::ArrayXd e3 = f * e1;
Eigen::ArrayXd e4 = eta * f;
Eigen::ArrayXd e5 = (e1_plus - e1_minus) / (2.0 * d_pi);
Eigen::ArrayXd e6 = (e2_plus - e2_minus) / (2.0 * d_pi);
Eigen::ArrayXd e7 = f * e5;
// Get C1 value (eqn 14) which is the end value of the e1 distribution
double c1 = e1[e1.rows()-1];
// Get A coefficients from equations A2 a-d
Eigen::ArrayXd a1 = e2 - e3 + shear_ratio * (e4 - e1);
Eigen::ArrayXd a2 = (-2.0 * e2) + e3 + (shear_ratio * e1);
Eigen::ArrayXd a3 = e6 - e7 - (shear_ratio * e5);
Eigen::ArrayXd a4 = (2.0 * e2) - e3 + (shear_ratio * e4) - (shear_ratio * 3.0 * e1);
// B coefficients are simply evaluated at eta = 1 (eqn A6)
double b1 = a1(eta.rows()-1);
double b2 = a2(eta.rows()-1);
double b3 = a3(eta.rows()-1);
double b4 = a4(eta.rows()-1);
// E1 from (eqn A4). Can't call it E1 due to name conflict with above.
double e1_coeff = 1.0 / (kappa * shear_ratio + 1.0);
// TODO Resolve issue #59 here.
double n = coles_wake(1.0, pi_coles);
// Compile f_i terms
Eigen::ArrayXd f1;
Eigen::ArrayXd f2;
Eigen::ArrayXd f3;
f1 = 1.0
- a1 / (b1 + e1_coeff * b2)
- e1_coeff * a2 / (b1 + e1_coeff * b2);
f2 = (e1_coeff * n * a2 * b1
+ a3 * b1
- e1_coeff * n * a1 * b2
+ e1_coeff * a3 * b2
- a1 * b3
- e1_coeff * a2 * b3) / (b1 + e1_coeff * b2);
f3 = (e1_coeff * a2 * b1
+ a4 * b1
- e1_coeff * a1 * b2
+ e1_coeff * a4 * b2
- a1 * b4
- e1_coeff * a2 * b4) / (b1 + e1_coeff * b2);
// Convert f2 and f3 into g1 and g2, apply eq. 15
Eigen::ArrayXd g1 = f2 / shear_ratio;
Eigen::ArrayXd g2 = -f3 / (c1 * shear_ratio);
Eigen::ArrayXd minus_r13 = f1 + g1 * zeta + g2 * beta;
// As a validation check, reproduce figure
Figure fig = Figure();
ScatterPlot p1 = ScatterPlot();
p1.x = eta;
p1.y = f1;
p1.name = "f1";
ScatterPlot p2 = ScatterPlot();
p2.x = eta;
p2.y = g1*zeta;
p2.name = "g1*zeta";
ScatterPlot p3 = ScatterPlot();
p3.x = eta;
p3.y = g2*beta;
p3.name = "g2*beta";
ScatterPlot p4 = ScatterPlot();
p4.x = eta;
p4.y = minus_r13;
p4.name = "tau / tau_0 (= -r13)";
fig.add(p1);
fig.add(p2);
fig.add(p3);
fig.add(p4);
Layout lay = Layout("Check reproduction of Perry & Marusic 1995 Figure 1");
lay.xTitle("$\\eta$");
fig.setLayout(lay);
fig.write("check_perry_marusic_fig_1");
Eigen::ArrayXd minus_r13_a(eta.rows());
if (lewkowicz) {
// Lewkowicz 1982 shear stress for equilibrium sink flow, Perry and Marusic eqn. 51
minus_r13_a = 1.0
- (60.0 / 59.0) * eta
- (20.0 / 59.0) * eta.pow(3.0)
+ (45.0 / 59.0) * eta.pow(4.0)
- (24.0 / 59.0) * eta.pow(5.0)
+ (60.0 / 59.0) * eta * eta.log();
} else {
// Shear stress for `pure` equilibrium sink flow with no correction, Perry and Marusic eqn. 53
minus_r13_a = 1.0 - eta + eta * eta.log();
}
// Handle the log(0) singularity
for (int i = 0; i < minus_r13_a.size(); i++) {
if (std::isinf(minus_r13_a(i)) || std::isnan(minus_r13_a(i))) {
minus_r13_a(i) = 1.0;
}
}
// Output correctly signed reynolds stress components
r13_a = -1.0 * minus_r13_a;
r13_b = -1.0 * (minus_r13 - minus_r13_a);
}
} /* namespace es */
#endif /* ES_FLOW_STRESS_H_ */