From 8f6355927f639b13d0e550f301e00d360baa981b Mon Sep 17 00:00:00 2001 From: Paul Dechamps <paul.dechamps@uliege.be> Date: Sun, 27 Oct 2024 19:33:16 +0100 Subject: [PATCH] (style) Format code + format check in pipeline --- .gitlab-ci.yml | 19 +- blast/_src/blastw.h | 4 +- blast/src/DBoundaryLayer.cpp | 658 +++++------ blast/src/DBoundaryLayer.h | 235 ++-- blast/src/DClosures.cpp | 440 +++---- blast/src/DClosures.h | 24 +- blast/src/DCoupledAdjoint.cpp | 2070 +++++++++++++++++---------------- blast/src/DCoupledAdjoint.h | 311 +++-- blast/src/DDriver.cpp | 1037 +++++++++-------- blast/src/DDriver.h | 83 +- blast/src/DFluxes.cpp | 463 +++++--- blast/src/DFluxes.h | 27 +- blast/src/DSolver.cpp | 290 +++-- blast/src/DSolver.h | 61 +- blast/src/blast.h | 3 +- format/format_cf11.py | 57 + 16 files changed, 3111 insertions(+), 2671 deletions(-) create mode 100755 format/format_cf11.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 07d7ee4..8647df9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,6 +24,21 @@ stages: - test - validation +format: + <<: *global_tag_def + stage: build + script: + - clang-format --version # we use clang-format-10 exclusively + - ./format/format_cf11.py + - mkdir -p patches + - if git diff --patch --exit-code > patches/clang-format.patch; then echo "Clang format changed nothing"; else echo "Clang format found changes to make!"; false; fi + artifacts: + paths: + - patches/ + expire_in: 1 day + when: on_failure + allow_failure: true + build: <<: *global_tag_def stage: build @@ -59,7 +74,6 @@ ctest: script: - cd build - ctest --output-on-failure -j 8 - #timeout: 10 hours # will be available in 12.3 dependencies: - build @@ -67,9 +81,12 @@ cvalidation: <<: *global_tag_def stage: validation script: + - set +e - python3 run.py blast/validation/raeValidation.py -v - python3 run.py blast/validation/oneraValidation.py -v - python3 run.py blast/validation/lannValidation.py -v + - set -e + - if [ $? -ne 0 ]; then exit 1; fi dependencies: - build when: manual diff --git a/blast/_src/blastw.h b/blast/_src/blastw.h index dd883e5..3d5c1f2 100644 --- a/blast/_src/blastw.h +++ b/blast/_src/blastw.h @@ -14,6 +14,6 @@ * limitations under the License. */ -#include "DDriver.h" #include "DBoundaryLayer.h" -#include "DCoupledAdjoint.h" \ No newline at end of file +#include "DCoupledAdjoint.h" +#include "DDriver.h" \ No newline at end of file diff --git a/blast/src/DBoundaryLayer.cpp b/blast/src/DBoundaryLayer.cpp index 5f84a69..cb81c81 100644 --- a/blast/src/DBoundaryLayer.cpp +++ b/blast/src/DBoundaryLayer.cpp @@ -11,111 +11,103 @@ using namespace blast; * * @param _xtrF Forced transition location (default=-1; free transition). */ -BoundaryLayer::BoundaryLayer(double _xtrF, std::string _name) -{ - xtrF = _xtrF; - name = _name; - xtr = 1.0; - closSolver = new Closures(); - transitionNode = 0; +BoundaryLayer::BoundaryLayer(double _xtrF, std::string _name) { + xtrF = _xtrF; + name = _name; + xtr = 1.0; + closSolver = new Closures(); + transitionNode = 0; } -BoundaryLayer::~BoundaryLayer() -{ - delete closSolver; -} - -void BoundaryLayer::setMesh(std::vector<double> _x, std::vector<double> _y, std::vector<double> _z, double _chord, double _xMin, std::vector<int> const _rows, std::vector<int> const _no) -{ - if (_x.size() != _y.size() || _x.size() != _z.size()) - throw std::runtime_error("Mesh coordinates are not consistent."); - nNodes = _x.size(); - nElms = nNodes - 1; - if (_rows.size() == 0) - { - rows.resize(0); - for (size_t i = 0; i < nNodes; ++i) - rows.push_back(static_cast<int>(i)); - } - else if (_rows.size() != nNodes) - throw std::runtime_error("Row vector is not consistent."); - else - { - rows = _rows; - } - // Elements - if (_no.size() == 0) - { - no.resize(0); - for (size_t i = 0; i < nElms; ++i) - no.push_back(static_cast<int>(i)); - } - else if (_no.size() != nElms) - throw std::runtime_error("No vector is not consistent."); - else - { - no = _no; - } - - x = _x; - y = _y; - z = _z; - chord = _chord; - xMin = _xMin; - - // Compute the local coordinate. - this->computeLocalCoordinates(); - this->reset(); +BoundaryLayer::~BoundaryLayer() { delete closSolver; } + +void BoundaryLayer::setMesh(std::vector<double> _x, std::vector<double> _y, + std::vector<double> _z, double _chord, double _xMin, + std::vector<int> const _rows, + std::vector<int> const _no) { + if (_x.size() != _y.size() || _x.size() != _z.size()) + throw std::runtime_error("Mesh coordinates are not consistent."); + nNodes = _x.size(); + nElms = nNodes - 1; + if (_rows.size() == 0) { + rows.resize(0); + for (size_t i = 0; i < nNodes; ++i) + rows.push_back(static_cast<int>(i)); + } else if (_rows.size() != nNodes) + throw std::runtime_error("Row vector is not consistent."); + else { + rows = _rows; + } + // Elements + if (_no.size() == 0) { + no.resize(0); + for (size_t i = 0; i < nElms; ++i) + no.push_back(static_cast<int>(i)); + } else if (_no.size() != nElms) + throw std::runtime_error("No vector is not consistent."); + else { + no = _no; + } + + x = _x; + y = _y; + z = _z; + chord = _chord; + xMin = _xMin; + + // Compute the local coordinate. + this->computeLocalCoordinates(); + this->reset(); } -void BoundaryLayer::computeLocalCoordinates() -{ - loc.resize(nNodes, 0.); - alpha.resize(nElms, 0.); - dx.resize(nElms, 0.); - - for (size_t iPoint = 0; iPoint < nElms; ++iPoint) - { - alpha[iPoint] = std::atan2(y[iPoint + 1] - y[iPoint], x[iPoint + 1] - x[iPoint]); - // dx = sqrt(delta x ^2 + delta y ^2). - dx[iPoint] = std::sqrt((x[iPoint + 1] - x[iPoint]) * (x[iPoint + 1] - x[iPoint]) + (y[iPoint + 1] - y[iPoint]) * (y[iPoint + 1] - y[iPoint])); - loc[iPoint + 1] = loc[iPoint] + dx[iPoint]; - } - - // Compute the x/c coordinate. - if (chord <= 0) - throw std::runtime_error("Chord length is zero or negative."); - xoc.resize(nNodes, 0.); - for (size_t iPoint = 0; iPoint < nNodes; ++iPoint) - xoc[iPoint] = (x[iPoint] - xMin) / chord; +void BoundaryLayer::computeLocalCoordinates() { + loc.resize(nNodes, 0.); + alpha.resize(nElms, 0.); + dx.resize(nElms, 0.); + + for (size_t iPoint = 0; iPoint < nElms; ++iPoint) { + alpha[iPoint] = + std::atan2(y[iPoint + 1] - y[iPoint], x[iPoint + 1] - x[iPoint]); + // dx = sqrt(delta x ^2 + delta y ^2). + dx[iPoint] = + std::sqrt((x[iPoint + 1] - x[iPoint]) * (x[iPoint + 1] - x[iPoint]) + + (y[iPoint + 1] - y[iPoint]) * (y[iPoint + 1] - y[iPoint])); + loc[iPoint + 1] = loc[iPoint] + dx[iPoint]; + } + + // Compute the x/c coordinate. + if (chord <= 0) + throw std::runtime_error("Chord length is zero or negative."); + xoc.resize(nNodes, 0.); + for (size_t iPoint = 0; iPoint < nNodes; ++iPoint) + xoc[iPoint] = (x[iPoint] - xMin) / chord; } -void BoundaryLayer::reset() -{ - u.resize(nNodes*getnVar(), 0.); - Ret.resize(nNodes, 0.); - cd.resize(nNodes, 0.); - cf.resize(nNodes, 0.); - Hstar.resize(nNodes, 0.); - Hstar2.resize(nNodes, 0.); - Hk.resize(nNodes, 0.); - ctEq.resize(nNodes, 0.); - us.resize(nNodes, 0.); - deltaStar.resize(nNodes, 0.); - delta.resize(nNodes, 0.); - deltaStar.resize(nNodes, 0.); - regime.resize(nNodes, 0); - blowingVelocity.resize(nElms, 0.); - - Me.resize(nNodes, 0.); - vt.resize(nNodes, 0.); - rhoe.resize(nNodes, 0.); - deltaStarExt.resize(nNodes, 0.); - vtExt.resize(nNodes, 0.); - xxExt.resize(nNodes, 0.); - - transitionNode = 0; - xtr = 1.0; +void BoundaryLayer::reset() { + u.resize(nNodes * getnVar(), 0.); + Ret.resize(nNodes, 0.); + cd.resize(nNodes, 0.); + cf.resize(nNodes, 0.); + Hstar.resize(nNodes, 0.); + Hstar2.resize(nNodes, 0.); + Hk.resize(nNodes, 0.); + ctEq.resize(nNodes, 0.); + us.resize(nNodes, 0.); + deltaStar.resize(nNodes, 0.); + delta.resize(nNodes, 0.); + deltaStar.resize(nNodes, 0.); + regime.resize(nNodes, 0); + blowingVelocity.resize(nElms, 0.); + + Me.resize(nNodes, 0.); + vt.resize(nNodes, 0.); + rhoe.resize(nNodes, 0.); + deltaStarExt.resize(nNodes, 0.); + vtExt.resize(nNodes, 0.); + xxExt.resize(nNodes, 0.); + + transitionNode = 0; + xtr = 1.0; } /** @@ -123,37 +115,35 @@ void BoundaryLayer::reset() * * @param Re Freestream Reynolds number. */ -void BoundaryLayer::setStagnationBC(double Re) -{ - double dv0 = std::abs((vt[1] - vt[0]) / (loc[1] - loc[0])); - if (dv0 > 0) - u[0] = sqrt(0.075 / (Re * dv0)); // Theta - else - u[0] = 1e-6; // Theta - u[1] = 2.23; // H - u[2] = 0.; // N - u[3] = vt[0]; // ue - u[4] = 0.; // Ctau - - Ret[0] = u[3] * u[0] * Re; - if (Ret[0] < 1) - { - Ret[0] = 1.; - u[3] = Ret[0] / (u[0] * Re); - } - deltaStar[0] = u[0] * u[1]; - - std::vector<double> lamParam(8, 0.); - closSolver->laminarClosures(lamParam, u[0], u[1], Ret[0], Me[0], name); - - Hstar[0] = lamParam[0]; - Hstar2[0] = lamParam[1]; - Hk[0] = lamParam[2]; - cf[0] = lamParam[3]; - cd[0] = lamParam[4]; - delta[0] = lamParam[5]; - ctEq[0] = lamParam[6]; - us[0] = lamParam[7]; +void BoundaryLayer::setStagnationBC(double Re) { + double dv0 = std::abs((vt[1] - vt[0]) / (loc[1] - loc[0])); + if (dv0 > 0) + u[0] = sqrt(0.075 / (Re * dv0)); // Theta + else + u[0] = 1e-6; // Theta + u[1] = 2.23; // H + u[2] = 0.; // N + u[3] = vt[0]; // ue + u[4] = 0.; // Ctau + + Ret[0] = u[3] * u[0] * Re; + if (Ret[0] < 1) { + Ret[0] = 1.; + u[3] = Ret[0] / (u[0] * Re); + } + deltaStar[0] = u[0] * u[1]; + + std::vector<double> lamParam(8, 0.); + closSolver->laminarClosures(lamParam, u[0], u[1], Ret[0], Me[0], name); + + Hstar[0] = lamParam[0]; + Hstar2[0] = lamParam[1]; + Hk[0] = lamParam[2]; + cf[0] = lamParam[3]; + cd[0] = lamParam[4]; + delta[0] = lamParam[5]; + ctEq[0] = lamParam[6]; + us[0] = lamParam[7]; } /** @@ -163,206 +153,225 @@ void BoundaryLayer::setStagnationBC(double Re) * @param UpperCond Variables at the last point on the upper side. * @param LowerCond Variables at the last point on the lower side. */ -void BoundaryLayer::setWakeBC(double Re, std::vector<double> UpperCond, std::vector<double> LowerCond) -{ - if (name != "wake") - std::cout << "Warning: Imposing wake boundary condition on " << name << std::endl; - u[0] = UpperCond[0] + LowerCond[0]; // (Theta_up+Theta_low). - u[1] = (UpperCond[0] * UpperCond[1] + LowerCond[0] * LowerCond[1]) / u[0]; // ((Theta*H)_up+(Theta*H)_low)/(Theta_up+Theta_low). - u[2] = 9.; // Amplification factor. - u[3] = vt[0]; // Inviscid velocity. - u[4] = (UpperCond[0] * UpperCond[4] + LowerCond[0] * LowerCond[4]) / u[0]; // ((Ct*Theta)_up+(Theta)_low)/(Ct*Theta_up+Theta_low). - - Ret[0] = u[3] * u[0] * Re; // Reynolds number based on the momentum thickness. - - if (Ret[0] < 1) - { - Ret[0] = 1; - u[3] = Ret[0] / (u[0] * Re); - } - deltaStar[0] = u[0] * u[1]; - - // Laminar closures. - std::vector<double> lamParam(8, 0.); - closSolver->laminarClosures(lamParam, u[0], u[1], Ret[0], Me[0], name); - Hstar[0] = lamParam[0]; - Hstar2[0] = lamParam[1]; - Hk[0] = lamParam[2]; - cf[0] = lamParam[3]; - cd[0] = lamParam[4]; - delta[0] = lamParam[5]; - ctEq[0] = lamParam[6]; - us[0] = lamParam[7]; - - for (size_t k = 0; k < nNodes; ++k) - regime[k] = 1; +void BoundaryLayer::setWakeBC(double Re, std::vector<double> UpperCond, + std::vector<double> LowerCond) { + if (name != "wake") + std::cout << "Warning: Imposing wake boundary condition on " << name + << std::endl; + u[0] = UpperCond[0] + LowerCond[0]; // (Theta_up+Theta_low). + u[1] = (UpperCond[0] * UpperCond[1] + LowerCond[0] * LowerCond[1]) / + u[0]; // ((Theta*H)_up+(Theta*H)_low)/(Theta_up+Theta_low). + u[2] = 9.; // Amplification factor. + u[3] = vt[0]; // Inviscid velocity. + u[4] = (UpperCond[0] * UpperCond[4] + LowerCond[0] * LowerCond[4]) / + u[0]; // ((Ct*Theta)_up+(Theta)_low)/(Ct*Theta_up+Theta_low). + + Ret[0] = u[3] * u[0] * Re; // Reynolds number based on the momentum thickness. + + if (Ret[0] < 1) { + Ret[0] = 1; + u[3] = Ret[0] / (u[0] * Re); + } + deltaStar[0] = u[0] * u[1]; + + // Laminar closures. + std::vector<double> lamParam(8, 0.); + closSolver->laminarClosures(lamParam, u[0], u[1], Ret[0], Me[0], name); + Hstar[0] = lamParam[0]; + Hstar2[0] = lamParam[1]; + Hk[0] = lamParam[2]; + cf[0] = lamParam[3]; + cd[0] = lamParam[4]; + delta[0] = lamParam[5]; + ctEq[0] = lamParam[6]; + us[0] = lamParam[7]; + + for (size_t k = 0; k < nNodes; ++k) + regime[k] = 1; } /** * @brief Compute the blowing velocity in each station of the region. * */ -void BoundaryLayer::computeBlowingVelocity() -{ - blowingVelocity.resize(nNodes - 1, 0.); - for (size_t i = 1; i < nNodes; ++i) - { - blowingVelocity[i - 1] = (rhoe[i] * vt[i] * deltaStar[i] - rhoe[i-1] * vt[i-1] * deltaStar[i - 1]) / (rhoe[i] * (loc[i] - loc[i-1])); - if (std::isnan(blowingVelocity[i - 1])) - { - if (rhoe[i] == 0.) - std::cout << "Density is zero at point " << i << std::endl; - if ((loc[i] - loc[i-1]) == 0.) - std::cout << "Points " << i -1 << " and " << i << " are at the same position " << loc[i] << ", resulting in an infinite gradient." << std::endl; - if (std::isnan(deltaStar[i])) - std::cout << "Displacement thickness is nan at position " << i << std::endl; - if (std::isnan(deltaStar[i - 1])) - std::cout << "Displacement thickness is nan at position " << i - 1 << std::endl; - throw std::runtime_error("NaN detected in blowing velocity computation (see reason above)"); - } +void BoundaryLayer::computeBlowingVelocity() { + blowingVelocity.resize(nNodes - 1, 0.); + for (size_t i = 1; i < nNodes; ++i) { + blowingVelocity[i - 1] = (rhoe[i] * vt[i] * deltaStar[i] - + rhoe[i - 1] * vt[i - 1] * deltaStar[i - 1]) / + (rhoe[i] * (loc[i] - loc[i - 1])); + if (std::isnan(blowingVelocity[i - 1])) { + if (rhoe[i] == 0.) + std::cout << "Density is zero at point " << i << std::endl; + if ((loc[i] - loc[i - 1]) == 0.) + std::cout << "Points " << i - 1 << " and " << i + << " are at the same position " << loc[i] + << ", resulting in an infinite gradient." << std::endl; + if (std::isnan(deltaStar[i])) + std::cout << "Displacement thickness is nan at position " << i + << std::endl; + if (std::isnan(deltaStar[i - 1])) + std::cout << "Displacement thickness is nan at position " << i - 1 + << std::endl; + throw std::runtime_error( + "NaN detected in blowing velocity computation (see reason above)"); } + } } -std::vector<std::vector<double>> BoundaryLayer::evalGradwrtDeltaStar() -{ - std::vector<std::vector<double>> gradVe = std::vector<std::vector<double>>(nElms); - for (auto &vec : gradVe) - vec.resize(nNodes, 0.); - - for (size_t i = 1; i < nNodes; ++i) - { - gradVe[i-1][i] = vt[i] / (loc[i] - loc[i-1]); - gradVe[i-1][i-1] = -1/rhoe[i] * rhoe[i-1] * vt[i-1] / (loc[i] - loc[i-1]); - } - return gradVe; +std::vector<std::vector<double>> BoundaryLayer::evalGradwrtDeltaStar() { + std::vector<std::vector<double>> gradVe = + std::vector<std::vector<double>>(nElms); + for (auto &vec : gradVe) + vec.resize(nNodes, 0.); + + for (size_t i = 1; i < nNodes; ++i) { + gradVe[i - 1][i] = vt[i] / (loc[i] - loc[i - 1]); + gradVe[i - 1][i - 1] = + -1 / rhoe[i] * rhoe[i - 1] * vt[i - 1] / (loc[i] - loc[i - 1]); + } + return gradVe; } -std::vector<std::vector<double>> BoundaryLayer::evalGradwrtVt() -{ - std::vector<std::vector<double>> gradVe = std::vector<std::vector<double>>(nElms); - for (auto &vec : gradVe) - vec.resize(nNodes, 0.); - - for (size_t i = 1; i < nNodes; ++i) - { - gradVe[i-1][i] = deltaStar[i] / (loc[i] - loc[i-1]); - gradVe[i-1][i - 1] = - rhoe[i-1] / rhoe[i] * deltaStar[i-1] / (loc[i] - loc[i-1]); - } - return gradVe; +std::vector<std::vector<double>> BoundaryLayer::evalGradwrtVt() { + std::vector<std::vector<double>> gradVe = + std::vector<std::vector<double>>(nElms); + for (auto &vec : gradVe) + vec.resize(nNodes, 0.); + + for (size_t i = 1; i < nNodes; ++i) { + gradVe[i - 1][i] = deltaStar[i] / (loc[i] - loc[i - 1]); + gradVe[i - 1][i - 1] = + -rhoe[i - 1] / rhoe[i] * deltaStar[i - 1] / (loc[i] - loc[i - 1]); + } + return gradVe; } -std::vector<std::vector<double>> BoundaryLayer::evalGradwrtRho() -{ - std::vector<std::vector<double>> gradVe = std::vector<std::vector<double>>(nElms); - for (auto &vec : gradVe) - vec.resize(nNodes, 0.); - - for (size_t i = 1; i < nNodes; ++i) - { - gradVe[i-1][i] = -1/(rhoe[i]*rhoe[i]) * ((rhoe[i] * vt[i] * deltaStar[i] - rhoe[i-1] * vt[i-1] * deltaStar[i-1])/(loc[i] - loc[i-1])) - + 1/rhoe[i] * vt[i] * deltaStar[i] / (loc[i] - loc[i-1]); - gradVe[i-1][i-1] = -vt[i-1] * deltaStar[i-1] / (rhoe[i] * (loc[i] - loc[i-1])); - } - return gradVe; +std::vector<std::vector<double>> BoundaryLayer::evalGradwrtRho() { + std::vector<std::vector<double>> gradVe = + std::vector<std::vector<double>>(nElms); + for (auto &vec : gradVe) + vec.resize(nNodes, 0.); + + for (size_t i = 1; i < nNodes; ++i) { + gradVe[i - 1][i] = + -1 / (rhoe[i] * rhoe[i]) * + ((rhoe[i] * vt[i] * deltaStar[i] - + rhoe[i - 1] * vt[i - 1] * deltaStar[i - 1]) / + (loc[i] - loc[i - 1])) + + 1 / rhoe[i] * vt[i] * deltaStar[i] / (loc[i] - loc[i - 1]); + gradVe[i - 1][i - 1] = + -vt[i - 1] * deltaStar[i - 1] / (rhoe[i] * (loc[i] - loc[i - 1])); + } + return gradVe; } /** * @brief Compute the gradient of the velocity with respect to the x coordinate. - * + * * dVe_dx = dVe_dloc * dloc_dx * - * @return std::vector<double> Gradient of the velocity with respect to the x coordinate. + * @return std::vector<double> Gradient of the velocity with respect to the x + * coordinate. */ -std::vector<std::vector<double>> BoundaryLayer::evalGradwrtX() -{ - std::vector<std::vector<double>> gradVe = std::vector<std::vector<double>>(nElms); - for (auto &vec : gradVe) - vec.resize(nNodes, 0.); - - // Compute dVe/dloc - std::vector<std::vector<double>> gradVe_loc = std::vector<std::vector<double>>(nElms); - for (auto &vec : gradVe_loc) - vec.resize(nNodes, 0.); - - for (size_t i = 1; i < nNodes; ++i) - { - double val = 1/rhoe[i] * (rhoe[i] * vt[i] * deltaStar[i] - rhoe[i-1] * vt[i-1] * deltaStar[i-1]) / ((loc[i] - loc[i-1]) * (loc[i] - loc[i-1])); - gradVe_loc[i-1][i] = -val; - gradVe_loc[i-1][i-1] = val; - } - - // Compute dloc/dx - // Derivative wrt x_j = (x_j - x_j-1) / sqrt((x_j - x_j-1)^2 + (y_j - y_j-1)^2) - // Derivative wrt x_j-1 = - (x_j - x_j-1) / sqrt((x_j - x_j-1)^2 + (y_j - y_j-1)^2) = - dloc/dx_j - // For loc_i, there are two contributions of x_j except if j = i. - // loc_n = sqrt((xn-xn-1)^2) + sqrt((xn-1-xn-2)^2) + ... + sqrt((x1-x0)^2) - std::vector<std::vector<double>> gradloc_x = std::vector<std::vector<double>>(nNodes); - for (auto &vec : gradloc_x) - vec.resize(nNodes, 0.); - - for (size_t j = 1; j < nNodes; ++j) - { - gradloc_x[j][j] = (x[j] - x[j-1]) / std::sqrt((x[j] - x[j-1]) * (x[j] - x[j-1]) + (y[j] - y[j-1]) * (y[j] - y[j-1])); - for (size_t i = 0; i < nNodes - j; ++i) - gradloc_x[j+i][j-1] = gradloc_x[j-1][j-1] - gradloc_x[j][j]; - } - - // Matrix product of gradVe_loc and gradloc_x - for (size_t i = 0; i < nElms; ++i) - { - for (size_t j = 0; j < nNodes; ++j) - { - for (size_t k = 0; k < nNodes; ++k) - gradVe[i][j] += gradVe_loc[i][k] * gradloc_x[k][j]; - } +std::vector<std::vector<double>> BoundaryLayer::evalGradwrtX() { + std::vector<std::vector<double>> gradVe = + std::vector<std::vector<double>>(nElms); + for (auto &vec : gradVe) + vec.resize(nNodes, 0.); + + // Compute dVe/dloc + std::vector<std::vector<double>> gradVe_loc = + std::vector<std::vector<double>>(nElms); + for (auto &vec : gradVe_loc) + vec.resize(nNodes, 0.); + + for (size_t i = 1; i < nNodes; ++i) { + double val = 1 / rhoe[i] * + (rhoe[i] * vt[i] * deltaStar[i] - + rhoe[i - 1] * vt[i - 1] * deltaStar[i - 1]) / + ((loc[i] - loc[i - 1]) * (loc[i] - loc[i - 1])); + gradVe_loc[i - 1][i] = -val; + gradVe_loc[i - 1][i - 1] = val; + } + + // Compute dloc/dx + // Derivative wrt x_j = (x_j - x_j-1) / sqrt((x_j - x_j-1)^2 + (y_j - + // y_j-1)^2) Derivative wrt x_j-1 = - (x_j - x_j-1) / sqrt((x_j - x_j-1)^2 + + // (y_j - y_j-1)^2) = - dloc/dx_j For loc_i, there are two contributions of + // x_j except if j = i. loc_n = sqrt((xn-xn-1)^2) + sqrt((xn-1-xn-2)^2) + ... + // + sqrt((x1-x0)^2) + std::vector<std::vector<double>> gradloc_x = + std::vector<std::vector<double>>(nNodes); + for (auto &vec : gradloc_x) + vec.resize(nNodes, 0.); + + for (size_t j = 1; j < nNodes; ++j) { + gradloc_x[j][j] = + (x[j] - x[j - 1]) / std::sqrt((x[j] - x[j - 1]) * (x[j] - x[j - 1]) + + (y[j] - y[j - 1]) * (y[j] - y[j - 1])); + for (size_t i = 0; i < nNodes - j; ++i) + gradloc_x[j + i][j - 1] = gradloc_x[j - 1][j - 1] - gradloc_x[j][j]; + } + + // Matrix product of gradVe_loc and gradloc_x + for (size_t i = 0; i < nElms; ++i) { + for (size_t j = 0; j < nNodes; ++j) { + for (size_t k = 0; k < nNodes; ++k) + gradVe[i][j] += gradVe_loc[i][k] * gradloc_x[k][j]; } - return gradVe; + } + return gradVe; } -std::vector<std::vector<double>> BoundaryLayer::evalGradwrtY() -{ - std::vector<std::vector<double>> gradVe = std::vector<std::vector<double>>(nElms); - for (auto &vec : gradVe) - vec.resize(nNodes, 0.); - - // Compute dVe/dloc - std::vector<std::vector<double>> gradVe_loc = std::vector<std::vector<double>>(nElms); - for (auto &vec : gradVe_loc) - vec.resize(nNodes, 0.); - - for (size_t i = 1; i < nNodes; ++i) - { - double val = 1/rhoe[i] * (rhoe[i] * vt[i] * deltaStar[i] - rhoe[i-1] * vt[i-1] * deltaStar[i-1]) / ((loc[i] - loc[i-1]) * (loc[i] - loc[i-1])); - gradVe_loc[i-1][i] = -val; - gradVe_loc[i-1][i-1] = val; - } - - // Compute dloc/dy - // Derivative wrt y_j = (y_j - y_j-1) / sqrt((y_j - y_j-1)^2 + (y_j - y_j-1)^2) - // Derivative wrt y_j-1 = - (y_j - y_j-1) / sqrt((y_j - y_j-1)^2 + (y_j - y_j-1)^2) = - dloc/dy_j - // For loc_i, there are two contributions of y_j except if j = i. - // loc_n = sqrt((yn-yn-1)^2) + sqrt((yn-1-yn-2)^2) + ... + sqrt((y1-y0)^2) - std::vector<std::vector<double>> gradloc_y = std::vector<std::vector<double>>(nNodes); - for (auto &vec : gradloc_y) - vec.resize(nNodes, 0.); - - for (size_t j = 1; j < nNodes; ++j) - { - gradloc_y[j][j] = (y[j] - y[j-1]) / std::sqrt((x[j] - x[j-1]) * (x[j] - x[j-1]) + (y[j] - y[j-1]) * (y[j] - y[j-1])); - for (size_t i = 0; i < nNodes - j; ++i) - gradloc_y[j+i][j-1] = gradloc_y[j-1][j-1] - gradloc_y[j][j]; - } - - // Matrix product of gradVe_loc and gradloc_x - for (size_t i = 0; i < nElms; ++i) - { - for (size_t j = 0; j < nNodes; ++j) - { - for (size_t k = 0; k < nNodes; ++k) - gradVe[i][j] += gradVe_loc[i][k] * gradloc_y[k][j]; - } +std::vector<std::vector<double>> BoundaryLayer::evalGradwrtY() { + std::vector<std::vector<double>> gradVe = + std::vector<std::vector<double>>(nElms); + for (auto &vec : gradVe) + vec.resize(nNodes, 0.); + + // Compute dVe/dloc + std::vector<std::vector<double>> gradVe_loc = + std::vector<std::vector<double>>(nElms); + for (auto &vec : gradVe_loc) + vec.resize(nNodes, 0.); + + for (size_t i = 1; i < nNodes; ++i) { + double val = 1 / rhoe[i] * + (rhoe[i] * vt[i] * deltaStar[i] - + rhoe[i - 1] * vt[i - 1] * deltaStar[i - 1]) / + ((loc[i] - loc[i - 1]) * (loc[i] - loc[i - 1])); + gradVe_loc[i - 1][i] = -val; + gradVe_loc[i - 1][i - 1] = val; + } + + // Compute dloc/dy + // Derivative wrt y_j = (y_j - y_j-1) / sqrt((y_j - y_j-1)^2 + (y_j - + // y_j-1)^2) Derivative wrt y_j-1 = - (y_j - y_j-1) / sqrt((y_j - y_j-1)^2 + + // (y_j - y_j-1)^2) = - dloc/dy_j For loc_i, there are two contributions of + // y_j except if j = i. loc_n = sqrt((yn-yn-1)^2) + sqrt((yn-1-yn-2)^2) + ... + // + sqrt((y1-y0)^2) + std::vector<std::vector<double>> gradloc_y = + std::vector<std::vector<double>>(nNodes); + for (auto &vec : gradloc_y) + vec.resize(nNodes, 0.); + + for (size_t j = 1; j < nNodes; ++j) { + gradloc_y[j][j] = + (y[j] - y[j - 1]) / std::sqrt((x[j] - x[j - 1]) * (x[j] - x[j - 1]) + + (y[j] - y[j - 1]) * (y[j] - y[j - 1])); + for (size_t i = 0; i < nNodes - j; ++i) + gradloc_y[j + i][j - 1] = gradloc_y[j - 1][j - 1] - gradloc_y[j][j]; + } + + // Matrix product of gradVe_loc and gradloc_x + for (size_t i = 0; i < nElms; ++i) { + for (size_t j = 0; j < nNodes; ++j) { + for (size_t k = 0; k < nNodes; ++k) + gradVe[i][j] += gradVe_loc[i][k] * gradloc_y[k][j]; } - return gradVe; + } + return gradVe; } /** @@ -371,22 +380,23 @@ std::vector<std::vector<double>> BoundaryLayer::evalGradwrtY() * @param iPoint Node id. * @note Function used for debugging. */ -void BoundaryLayer::printSolution(size_t iPoint) const -{ - if (iPoint < 0 || iPoint > nNodes-1) - throw std::runtime_error("Tried to access element outside of region size."); - std::cout << "Pt " << iPoint << "Reg " << name << " Turb " << regime[iPoint] << std::endl; - std::cout << std::setprecision(5) << "x " << x[iPoint] << ", xoc " << xoc[iPoint] << - ", xx " << loc[iPoint] << "xxExt " << xxExt[iPoint] << std::endl; - std::cout << std::scientific << std::setprecision(15); - std::cout << std::setw(10) << "T " << u[iPoint * nVar + 0] << "\n" - << std::setw(10) << "H " << u[iPoint * nVar + 1] << "\n" - << std::setw(10) << "N " << u[iPoint * nVar + 2] << "\n" - << std::setw(10) << "ue " << u[iPoint * nVar + 3] << "\n" - << std::setw(10) << "Ct " << u[iPoint * nVar + 4] << "\n" - << std::setw(10) << "dStar (BL) " << deltaStar[iPoint] << "\n" - << std::setw(10) << "dStar (ext) " << deltaStarExt[iPoint] << "\n" - << std::setw(10) << "vt " << vt[iPoint] << "\n" - << std::setw(10) << "Me " << Me[iPoint] << "\n" - << std::setw(10) << "rhoe " << rhoe[iPoint] << std::endl; +void BoundaryLayer::printSolution(size_t iPoint) const { + if (iPoint < 0 || iPoint > nNodes - 1) + throw std::runtime_error("Tried to access element outside of region size."); + std::cout << "Pt " << iPoint << "Reg " << name << " Turb " << regime[iPoint] + << std::endl; + std::cout << std::setprecision(5) << "x " << x[iPoint] << ", xoc " + << xoc[iPoint] << ", xx " << loc[iPoint] << "xxExt " + << xxExt[iPoint] << std::endl; + std::cout << std::scientific << std::setprecision(15); + std::cout << std::setw(10) << "T " << u[iPoint * nVar + 0] << "\n" + << std::setw(10) << "H " << u[iPoint * nVar + 1] << "\n" + << std::setw(10) << "N " << u[iPoint * nVar + 2] << "\n" + << std::setw(10) << "ue " << u[iPoint * nVar + 3] << "\n" + << std::setw(10) << "Ct " << u[iPoint * nVar + 4] << "\n" + << std::setw(10) << "dStar (BL) " << deltaStar[iPoint] << "\n" + << std::setw(10) << "dStar (ext) " << deltaStarExt[iPoint] << "\n" + << std::setw(10) << "vt " << vt[iPoint] << "\n" + << std::setw(10) << "Me " << Me[iPoint] << "\n" + << std::setw(10) << "rhoe " << rhoe[iPoint] << std::endl; } \ No newline at end of file diff --git a/blast/src/DBoundaryLayer.h b/blast/src/DBoundaryLayer.h index 5f7adb2..8710205 100644 --- a/blast/src/DBoundaryLayer.h +++ b/blast/src/DBoundaryLayer.h @@ -1,116 +1,159 @@ #ifndef DBOUNDARYLAYER_H #define DBOUNDARYLAYER_H +#include "DClosures.h" #include "blast.h" #include "wObject.h" -#include "DClosures.h" #include <algorithm> -namespace blast -{ +namespace blast { /** * @brief Boundary layer region upper/lower side or wake. * @author Paul Dechamps */ -class BLAST_API BoundaryLayer : public fwk::wSharedObject -{ +class BLAST_API BoundaryLayer : public fwk::wSharedObject { private: - unsigned int const nVar = 5; ///< Number of variables of the partial differential problem. - double nCrit = 9.0; ///< Critical amplification factor. + unsigned int const nVar = + 5; ///< Number of variables of the partial differential problem. + double nCrit = 9.0; ///< Critical amplification factor. public: - Closures *closSolver; ///< Closure relations class. - std::string name; ///< Name of the region. - - // Mesh - size_t nNodes; ///< Number of points in the domain. - size_t nElms; ///< Number of cells in the domain. - std::vector<double> x; ///< x coordinate in the global frame of reference. - std::vector<double> y; ///< y coordinate in the global frame of reference. - std::vector<double> z; ///< z coordinate in the global frame of reference. - std::vector<double> xoc; ///< x/c coordinate in the global frame of reference. - std::vector<double> loc; ///< xi coordinate in the local frame of reference. - std::vector<int> rows; ///< Reference numbers of the nodes. - std::vector<int> no; ///< Reference numbers of the nodes. - std::vector<double> dx; ///< Cell size. - std::vector<double> alpha; ///< Angle of the cell wrt the x axis of the global frame of reference. - double chord; ///< Chord of the section. - double xMin; ///< Minimum x coordinate of the mesh (for local coordinates computation). - - // Boundary layer variables. - std::vector<double> u; ///< Solution vector (theta, H, N, ue, Ct). - std::vector<double> Ret; ///< Reynolds number based on the momentum thickness (theta). - std::vector<double> cd; ///< Local dissipation coefficient. - std::vector<double> cf; ///< Local friction coefficient. - std::vector<double> Hstar; ///< Kinetic energy shape parameter (thetaStar/theta). - std::vector<double> Hstar2; ///< Density shape parameter (deltaStarStar/theta). - std::vector<double> Hk; ///< Kinematic shape parameter (int(1-u/ue d_eta)). - std::vector<double> ctEq; ///< Equilibrium shear stress coefficient (turbulent BL). - std::vector<double> us; ///< Equivalent normalized wall slip velocity. - std::vector<double> delta; ///< Boundary layer thickness. - std::vector<double> deltaStar; ///< Displacement thickness (int(1-rho*u/rhoe*ue d_eta)). - - std::vector<double> Me; ///< Mach number. - std::vector<double> vt; ///< Velocity. - std::vector<double> rhoe; ///< Density. - std::vector<double> xxExt; ///< xi coordinate in the local frame of reference, at the edge of the boundary layer. - std::vector<double> deltaStarExt; ///< Displacement thickness. - std::vector<double> vtExt; ///< Previous velocity. - - std::vector<double> blowingVelocity; ///< Blowing velocity. - - // Transition related variables. - std::vector<int> regime; ///< Laminar (0) or turbulent (1) regime. - size_t transitionNode; ///< Node id of the transition location. - double xtrF; ///< Forced transition location in the local frame of reference (x/c). - double xtr; ///< Transition location in the local frame of reference (x/c). - - BoundaryLayer(double _xtrF = -1.0, std::string _name = "None"); - ~BoundaryLayer(); - - void reset(); - - // Getters - std::string getName() const { return name; }; - size_t getnNodes() const { return nNodes; }; - size_t getnElms() const { return nElms; }; - - std::vector<double> getDeltaStar() const { return deltaStar; }; - std::vector<double> getUe() const {std::vector<double > ue(nNodes, 0.); for (size_t i = 0; i < nNodes; ++i) ue[i] = u[i * nVar + 3]; return ue;}; - std::vector<double> getBlowing() const { return blowingVelocity; }; - double getMaxMach() const { return *std::max_element(Me.begin(), Me.end()); }; - - // Setters - void setMesh(std::vector<double> const _x, std::vector<double> const y, std::vector<double> const z, double const _chord, double const _xMin, std::vector<int> const _rows=std::vector<int>(0), std::vector<int> const _no=std::vector<int>(0)); - void computeLocalCoordinates(); - void setMe(std::vector<double> const _Me) {if (_Me.size() != nNodes) throw std::runtime_error("Mach number vector is not consistent."); Me = _Me;}; - void setVt(std::vector<double> const _vt) {if (_vt.size() != nNodes) throw std::runtime_error("Velocity vector is not consistent."); vt = _vt;}; - void setRhoe(std::vector<double> const _rhoe) {if (_rhoe.size() != nNodes) throw std::runtime_error("Density vector is not consistent."); rhoe = _rhoe;}; - void setxxExt(std::vector<double> const _xxExt) {if (_xxExt.size() != nNodes) throw std::runtime_error("External mesh vector is not consistent."); xxExt = _xxExt;}; - void setDeltaStarExt(std::vector<double> const _deltaStarExt) {if (_deltaStarExt.size() != nNodes) throw std::runtime_error("Displacement thickness vector is not consistent."); deltaStarExt = _deltaStarExt;}; - void setVtExt(std::vector<double> const _vtExt) {if (_vtExt.size() != nNodes) throw std::runtime_error("Velocity vector is not consistent."); vtExt = _vtExt;}; - void setxtrF(double const _xtrF) {xtrF = _xtrF;}; - - // Boundary conditions. - void setStagnationBC(double Re); - void setWakeBC(double Re, std::vector<double> upperConditions, std::vector<double> lowerConditions); - - // Getters. - size_t getnVar() const { return nVar; }; - double getnCrit() const { return nCrit; }; - void setnCrit(double const _nCrit) {nCrit = _nCrit;}; - - // Others - void printSolution(size_t iPoint) const; - void computeBlowingVelocity(); - std::vector<std::vector<double>> evalGradwrtRho(); - std::vector<std::vector<double>> evalGradwrtVt(); - std::vector<std::vector<double>> evalGradwrtDeltaStar(); - std::vector<std::vector<double>> evalGradwrtX(); - std::vector<std::vector<double>> evalGradwrtY(); + Closures *closSolver; ///< Closure relations class. + std::string name; ///< Name of the region. + + // Mesh + size_t nNodes; ///< Number of points in the domain. + size_t nElms; ///< Number of cells in the domain. + std::vector<double> x; ///< x coordinate in the global frame of reference. + std::vector<double> y; ///< y coordinate in the global frame of reference. + std::vector<double> z; ///< z coordinate in the global frame of reference. + std::vector<double> xoc; ///< x/c coordinate in the global frame of reference. + std::vector<double> loc; ///< xi coordinate in the local frame of reference. + std::vector<int> rows; ///< Reference numbers of the nodes. + std::vector<int> no; ///< Reference numbers of the nodes. + std::vector<double> dx; ///< Cell size. + std::vector<double> alpha; ///< Angle of the cell wrt the x axis of the global + ///< frame of reference. + double chord; ///< Chord of the section. + double xMin; ///< Minimum x coordinate of the mesh (for local coordinates + ///< computation). + + // Boundary layer variables. + std::vector<double> u; ///< Solution vector (theta, H, N, ue, Ct). + std::vector<double> + Ret; ///< Reynolds number based on the momentum thickness (theta). + std::vector<double> cd; ///< Local dissipation coefficient. + std::vector<double> cf; ///< Local friction coefficient. + std::vector<double> + Hstar; ///< Kinetic energy shape parameter (thetaStar/theta). + std::vector<double> + Hstar2; ///< Density shape parameter (deltaStarStar/theta). + std::vector<double> Hk; ///< Kinematic shape parameter (int(1-u/ue d_eta)). + std::vector<double> + ctEq; ///< Equilibrium shear stress coefficient (turbulent BL). + std::vector<double> us; ///< Equivalent normalized wall slip velocity. + std::vector<double> delta; ///< Boundary layer thickness. + std::vector<double> + deltaStar; ///< Displacement thickness (int(1-rho*u/rhoe*ue d_eta)). + + std::vector<double> Me; ///< Mach number. + std::vector<double> vt; ///< Velocity. + std::vector<double> rhoe; ///< Density. + std::vector<double> xxExt; ///< xi coordinate in the local frame of reference, + ///< at the edge of the boundary layer. + std::vector<double> deltaStarExt; ///< Displacement thickness. + std::vector<double> vtExt; ///< Previous velocity. + + std::vector<double> blowingVelocity; ///< Blowing velocity. + + // Transition related variables. + std::vector<int> regime; ///< Laminar (0) or turbulent (1) regime. + size_t transitionNode; ///< Node id of the transition location. + double xtrF; ///< Forced transition location in the local frame of reference + ///< (x/c). + double xtr; ///< Transition location in the local frame of reference (x/c). + + BoundaryLayer(double _xtrF = -1.0, std::string _name = "None"); + ~BoundaryLayer(); + + void reset(); + + // Getters + std::string getName() const { return name; }; + size_t getnNodes() const { return nNodes; }; + size_t getnElms() const { return nElms; }; + + std::vector<double> getDeltaStar() const { return deltaStar; }; + std::vector<double> getUe() const { + std::vector<double> ue(nNodes, 0.); + for (size_t i = 0; i < nNodes; ++i) + ue[i] = u[i * nVar + 3]; + return ue; + }; + std::vector<double> getBlowing() const { return blowingVelocity; }; + double getMaxMach() const { return *std::max_element(Me.begin(), Me.end()); }; + + // Setters + void setMesh(std::vector<double> const _x, std::vector<double> const y, + std::vector<double> const z, double const _chord, + double const _xMin, + std::vector<int> const _rows = std::vector<int>(0), + std::vector<int> const _no = std::vector<int>(0)); + void computeLocalCoordinates(); + void setMe(std::vector<double> const _Me) { + if (_Me.size() != nNodes) + throw std::runtime_error("Mach number vector is not consistent."); + Me = _Me; + }; + void setVt(std::vector<double> const _vt) { + if (_vt.size() != nNodes) + throw std::runtime_error("Velocity vector is not consistent."); + vt = _vt; + }; + void setRhoe(std::vector<double> const _rhoe) { + if (_rhoe.size() != nNodes) + throw std::runtime_error("Density vector is not consistent."); + rhoe = _rhoe; + }; + void setxxExt(std::vector<double> const _xxExt) { + if (_xxExt.size() != nNodes) + throw std::runtime_error("External mesh vector is not consistent."); + xxExt = _xxExt; + }; + void setDeltaStarExt(std::vector<double> const _deltaStarExt) { + if (_deltaStarExt.size() != nNodes) + throw std::runtime_error( + "Displacement thickness vector is not consistent."); + deltaStarExt = _deltaStarExt; + }; + void setVtExt(std::vector<double> const _vtExt) { + if (_vtExt.size() != nNodes) + throw std::runtime_error("Velocity vector is not consistent."); + vtExt = _vtExt; + }; + void setxtrF(double const _xtrF) { xtrF = _xtrF; }; + + // Boundary conditions. + void setStagnationBC(double Re); + void setWakeBC(double Re, std::vector<double> upperConditions, + std::vector<double> lowerConditions); + + // Getters. + size_t getnVar() const { return nVar; }; + double getnCrit() const { return nCrit; }; + void setnCrit(double const _nCrit) { nCrit = _nCrit; }; + + // Others + void printSolution(size_t iPoint) const; + void computeBlowingVelocity(); + std::vector<std::vector<double>> evalGradwrtRho(); + std::vector<std::vector<double>> evalGradwrtVt(); + std::vector<std::vector<double>> evalGradwrtDeltaStar(); + std::vector<std::vector<double>> evalGradwrtX(); + std::vector<std::vector<double>> evalGradwrtY(); }; } // namespace blast #endif // DBOUNDARYLAYER_H diff --git a/blast/src/DClosures.cpp b/blast/src/DClosures.cpp index 2cf9f44..53e872d 100644 --- a/blast/src/DClosures.cpp +++ b/blast/src/DClosures.cpp @@ -16,69 +16,66 @@ using namespace blast; */ void Closures::laminarClosures(std::vector<double> &closureVars, double theta, double H, double Ret, const double Me, - const std::string name) -{ - H = std::max(H, 1.00005); - - // Kinematic shape factor H*. - double Hk = (H - 0.29 * Me * Me) / (1 + 0.113 * Me * Me); - if (name == "wake") - Hk = std::max(Hk, 1.00005); - else - Hk = std::max(Hk, 1.05000); - - // Density shape parameter. - double Hstar2 = (0.064 / (Hk - 0.8) + 0.251) * Me * Me; - - // Boundary layer thickness. - double delta = std::min((3.15 + H + (1.72 / (Hk - 1))) * theta, 12 * theta); - - double Hstar = 0.; - double Hks = Hk - 4.35; - if (Hk <= 4.35) - Hstar = 0.0111 * Hks * Hks / (Hk + 1) - 0.0278 * Hks * Hks * Hks / (Hk + 1) + 1.528 - 0.0002 * (Hks * Hk) * (Hks * Hk); - else - Hstar = 1.528 + 0.015 * Hks * Hks / Hk; - - // Whitfield's minor additional compressibility correction. - Hstar = (Hstar + 0.028 * Me * Me) / (1 + 0.014 * Me * Me); - - // Friction coefficient. - double tmp = 0.; - double cf = 0.; - if (Hk < 5.5) - { - tmp = (5.5 - Hk) * (5.5 - Hk) * (5.5 - Hk) / (Hk + 1.0); - cf = (-0.07 + 0.0727 * tmp) / Ret; - } - else if (Hk >= 5.5) - { - tmp = 1.0 - 1.0 / (Hk - 4.5); - cf = (-0.07 + 0.015 * tmp * tmp) / Ret; - } - - // Dissipation coefficient. - double Cd = 0.; - if (Hk < 4) - Cd = (0.00205 * std::pow(4.0 - Hk, 5.5) + 0.207) * (Hstar / (2 * Ret)); - else - { - double HkCd = (Hk - 4) * (Hk - 4); - double denCd = 1 + 0.02 * HkCd; - Cd = (-0.0016 * HkCd / denCd + 0.207) * (Hstar / (2 * Ret)); - } - - // Wake relations. - if (name == "wake") - { - Cd = 2 * (1.10 * (1.0 - 1.0 / Hk) * (1.0 - 1.0 / Hk) / Hk) * (Hstar / (2 * Ret)); - cf = 0.; - } - - double us = 0.; - double ctEq = 0.; - - closureVars = {Hstar, Hstar2, Hk, cf, Cd, delta, ctEq, us}; + const std::string name) { + H = std::max(H, 1.00005); + + // Kinematic shape factor H*. + double Hk = (H - 0.29 * Me * Me) / (1 + 0.113 * Me * Me); + if (name == "wake") + Hk = std::max(Hk, 1.00005); + else + Hk = std::max(Hk, 1.05000); + + // Density shape parameter. + double Hstar2 = (0.064 / (Hk - 0.8) + 0.251) * Me * Me; + + // Boundary layer thickness. + double delta = std::min((3.15 + H + (1.72 / (Hk - 1))) * theta, 12 * theta); + + double Hstar = 0.; + double Hks = Hk - 4.35; + if (Hk <= 4.35) + Hstar = 0.0111 * Hks * Hks / (Hk + 1) - + 0.0278 * Hks * Hks * Hks / (Hk + 1) + 1.528 - + 0.0002 * (Hks * Hk) * (Hks * Hk); + else + Hstar = 1.528 + 0.015 * Hks * Hks / Hk; + + // Whitfield's minor additional compressibility correction. + Hstar = (Hstar + 0.028 * Me * Me) / (1 + 0.014 * Me * Me); + + // Friction coefficient. + double tmp = 0.; + double cf = 0.; + if (Hk < 5.5) { + tmp = (5.5 - Hk) * (5.5 - Hk) * (5.5 - Hk) / (Hk + 1.0); + cf = (-0.07 + 0.0727 * tmp) / Ret; + } else if (Hk >= 5.5) { + tmp = 1.0 - 1.0 / (Hk - 4.5); + cf = (-0.07 + 0.015 * tmp * tmp) / Ret; + } + + // Dissipation coefficient. + double Cd = 0.; + if (Hk < 4) + Cd = (0.00205 * std::pow(4.0 - Hk, 5.5) + 0.207) * (Hstar / (2 * Ret)); + else { + double HkCd = (Hk - 4) * (Hk - 4); + double denCd = 1 + 0.02 * HkCd; + Cd = (-0.0016 * HkCd / denCd + 0.207) * (Hstar / (2 * Ret)); + } + + // Wake relations. + if (name == "wake") { + Cd = 2 * (1.10 * (1.0 - 1.0 / Hk) * (1.0 - 1.0 / Hk) / Hk) * + (Hstar / (2 * Ret)); + cf = 0.; + } + + double us = 0.; + double ctEq = 0.; + + closureVars = {Hstar, Hstar2, Hk, cf, Cd, delta, ctEq, us}; } /** @@ -92,101 +89,114 @@ void Closures::laminarClosures(std::vector<double> &closureVars, double theta, * @param Me Local Mach number. * @param name Name of the region. */ -void Closures::turbulentClosures(std::vector<double> &closureVars, double theta, double H, double Ct, double Ret, const double Me, const std::string name) -{ - H = std::max(H, 1.00005); - Ct = std::min(Ct, 0.3); - // Ct = std::max(std::min(Ct, 0.30), 0.0000001); - - double Hk = (H - 0.29 * Me * Me) / (1 + 0.113 * Me * Me); - if (name == "wake") - Hk = std::max(Hk, 1.00005); - else - Hk = std::max(Hk, 1.05000); - - double Hstar2 = ((0.064 / (Hk - 0.8)) + 0.251) * Me * Me; - double gamma = 1.4 - 1.; - double Fc = std::sqrt(1 + 0.5 * gamma * Me * Me); - - double H0 = 0.; - if (Ret <= 400) - H0 = 4.0; - else - H0 = 3 + (400 / Ret); - if (Ret <= 200) - Ret = 200; - - double Hstar = 0.; - if (Hk <= H0) - Hstar = ((0.5 - 4 / Ret) * ((H0 - Hk) / (H0 - 1)) * ((H0 - Hk) / (H0 - 1))) * (1.5 / (Hk + 0.5)) + 1.5 + 4 / Ret; - else - Hstar = (Hk - H0) * (Hk - H0) * (0.007 * std::log(Ret) / ((Hk - H0 + 4 / std::log(Ret)) * (Hk - H0 + 4 / std::log(Ret))) + 0.015 / Hk) + 1.5 + 4 / Ret; - - // Whitfield's minor additional compressibility correction. - Hstar = (Hstar + 0.028 * Me * Me) / (1 + 0.014 * Me * Me); - - double logRt = std::log(Ret / Fc); - logRt = std::max(logRt, 3.0); - double arg = std::max(-1.33 * Hk, -20.0); - - // Equivalent normalized wall slip velocity. - double us = (Hstar / 2) * (1 - 4 * (Hk - 1) / (3 * H)); - - // Boundary layer thickness. - double delta = std::min((3.15 + H + (1.72 / (Hk - 1))) * theta, 12 * theta); - - double Ctcon = 0.5 / (6.7 * 6.7 * 0.75); - double Hkc = 0.; - double Cdw = 0.; - double Cdd = 0.; - double Cdl = 0.; - - double Hmin = 0.; - double Fl = 0.; - double Dfac = 0.; - - double cf = 0.; - double Cd = 0.; - - double n = 1.0; - - double ctEq = 0.; - - if (name == "wake") - { - if (us > 0.99995) - us = 0.99995; - n = 2.0; // two wake halves - cf = 0.0; // no friction inside the wake - Hkc = Hk - 1; - Cdw = 0.0; // Wall contribution. - Cdd = (0.995 - us) * Ct * Ct; // Turbulent outer layer contribution. - Cdl = 0.15 * (0.995 - us) * (0.995 - us) / Ret; // Laminar stress contribution to outer layer. - ctEq = std::sqrt(4 * Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / ((1 - us) * (Hk * Hk) * H)); // Here it is ctEq^0.5. - } - else - { - if (us > 0.95) - us = 0.98; - n = 1.0; - cf = (1 / Fc) * (0.3 * std::exp(arg) * std::pow(logRt / 2.3026, (-1.74 - 0.31 * Hk)) + 0.00011 * (std::tanh(4. - (Hk / 0.875)) - 1.)); - Hkc = std::max(Hk - 1. - 18. / Ret, 0.01); - // Dissipation coefficient. - Hmin = 1 + 2.1 / std::log(Ret); - Fl = (Hk - 1) / (Hmin - 1); - Dfac = 0.5 + 0.5 * std::tanh(Fl); - Cdw = 0.5 * (cf * us) * Dfac; - Cdd = (0.995 - us) * Ct * Ct; - Cdl = 0.15 * (0.995 - us) * (0.995 - us) / Ret; - ctEq = std::sqrt(Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / ((1 - us) * (Hk * Hk) * H)); // Here it is ctEq^0.5 - //ctEq = std::sqrt(Hstar * 0.015/(1-us) * (Hk-1)*(Hk-1)*(Hk-1)/(Hk*Hk*H)); // Drela 1987 - } - if (n * Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / ((1 - us) * (Hk * Hk) * H) < 0) - std::cout << "Negative sqrt encountered " << std::endl; - +void Closures::turbulentClosures(std::vector<double> &closureVars, double theta, + double H, double Ct, double Ret, + const double Me, const std::string name) { + H = std::max(H, 1.00005); + Ct = std::min(Ct, 0.3); + // Ct = std::max(std::min(Ct, 0.30), 0.0000001); + + double Hk = (H - 0.29 * Me * Me) / (1 + 0.113 * Me * Me); + if (name == "wake") + Hk = std::max(Hk, 1.00005); + else + Hk = std::max(Hk, 1.05000); + + double Hstar2 = ((0.064 / (Hk - 0.8)) + 0.251) * Me * Me; + double gamma = 1.4 - 1.; + double Fc = std::sqrt(1 + 0.5 * gamma * Me * Me); + + double H0 = 0.; + if (Ret <= 400) + H0 = 4.0; + else + H0 = 3 + (400 / Ret); + if (Ret <= 200) + Ret = 200; + + double Hstar = 0.; + if (Hk <= H0) + Hstar = + ((0.5 - 4 / Ret) * ((H0 - Hk) / (H0 - 1)) * ((H0 - Hk) / (H0 - 1))) * + (1.5 / (Hk + 0.5)) + + 1.5 + 4 / Ret; + else + Hstar = (Hk - H0) * (Hk - H0) * + (0.007 * std::log(Ret) / + ((Hk - H0 + 4 / std::log(Ret)) * + (Hk - H0 + 4 / std::log(Ret))) + + 0.015 / Hk) + + 1.5 + 4 / Ret; + + // Whitfield's minor additional compressibility correction. + Hstar = (Hstar + 0.028 * Me * Me) / (1 + 0.014 * Me * Me); + + double logRt = std::log(Ret / Fc); + logRt = std::max(logRt, 3.0); + double arg = std::max(-1.33 * Hk, -20.0); + + // Equivalent normalized wall slip velocity. + double us = (Hstar / 2) * (1 - 4 * (Hk - 1) / (3 * H)); + + // Boundary layer thickness. + double delta = std::min((3.15 + H + (1.72 / (Hk - 1))) * theta, 12 * theta); + + double Ctcon = 0.5 / (6.7 * 6.7 * 0.75); + double Hkc = 0.; + double Cdw = 0.; + double Cdd = 0.; + double Cdl = 0.; + + double Hmin = 0.; + double Fl = 0.; + double Dfac = 0.; + + double cf = 0.; + double Cd = 0.; + + double n = 1.0; + + double ctEq = 0.; + + if (name == "wake") { + if (us > 0.99995) + us = 0.99995; + n = 2.0; // two wake halves + cf = 0.0; // no friction inside the wake + Hkc = Hk - 1; + Cdw = 0.0; // Wall contribution. + Cdd = (0.995 - us) * Ct * Ct; // Turbulent outer layer contribution. + Cdl = 0.15 * (0.995 - us) * (0.995 - us) / + Ret; // Laminar stress contribution to outer layer. + ctEq = std::sqrt(4 * Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / + ((1 - us) * (Hk * Hk) * H)); // Here it is ctEq^0.5. + } else { + if (us > 0.95) + us = 0.98; + n = 1.0; + cf = (1 / Fc) * + (0.3 * std::exp(arg) * std::pow(logRt / 2.3026, (-1.74 - 0.31 * Hk)) + + 0.00011 * (std::tanh(4. - (Hk / 0.875)) - 1.)); + Hkc = std::max(Hk - 1. - 18. / Ret, 0.01); // Dissipation coefficient. - Cd = n * (Cdw + Cdd + Cdl); - closureVars = {Hstar, Hstar2, Hk, cf, Cd, delta, ctEq, us}; + Hmin = 1 + 2.1 / std::log(Ret); + Fl = (Hk - 1) / (Hmin - 1); + Dfac = 0.5 + 0.5 * std::tanh(Fl); + Cdw = 0.5 * (cf * us) * Dfac; + Cdd = (0.995 - us) * Ct * Ct; + Cdl = 0.15 * (0.995 - us) * (0.995 - us) / Ret; + ctEq = std::sqrt(Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / + ((1 - us) * (Hk * Hk) * H)); // Here it is ctEq^0.5 + // ctEq = std::sqrt(Hstar * 0.015/(1-us) * (Hk-1)*(Hk-1)*(Hk-1)/(Hk*Hk*H)); + // // Drela 1987 + } + if (n * Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / ((1 - us) * (Hk * Hk) * H) < + 0) + std::cout << "Negative sqrt encountered " << std::endl; + + // Dissipation coefficient. + Cd = n * (Cdw + Cdd + Cdl); + closureVars = {Hstar, Hstar2, Hk, cf, Cd, delta, ctEq, us}; } /** @@ -200,58 +210,66 @@ void Closures::turbulentClosures(std::vector<double> &closureVars, double theta, * @param Me Local Mach number. * @param name Name of the region. */ -void Closures::turbulentClosures(double &closureVars, double theta, double H, double Ct, double Ret, const double Me, const std::string name) -{ - H = std::max(H, 1.00005); - Ct = std::min(Ct, 0.3); - - double Hk = (H - 0.29 * Me * Me) / (1 + 0.113 * Me * Me); - if (name == "wake") - Hk = std::max(Hk, 1.00005); - else - Hk = std::max(Hk, 1.05000); - - double H0 = 0.; - if (Ret <= 400) - H0 = 4.0; - else - H0 = 3 + (400 / Ret); - if (Ret <= 200) - Ret = 200; - - double Hstar = 0.; - if (Hk <= H0) - Hstar = ((0.5 - 4 / Ret) * ((H0 - Hk) / (H0 - 1)) * ((H0 - Hk) / (H0 - 1))) * (1.5 / (Hk + 0.5)) + 1.5 + 4 / Ret; - else - Hstar = (Hk - H0) * (Hk - H0) * (0.007 * std::log(Ret) / ((Hk - H0 + 4 / std::log(Ret)) * (Hk - H0 + 4 / std::log(Ret))) + 0.015 / Hk) + 1.5 + 4 / Ret; - - // Whitfield's minor additional compressibility correction. - Hstar = (Hstar + 0.028 * Me * Me) / (1 + 0.014 * Me * Me); - - // Equivalent normalized wall slip velocity. - double us = (Hstar / 2) * (1 - 4 * (Hk - 1) / (3 * H)); - - double Ctcon = 0.5 / (6.7 * 6.7 * 0.75); - - double Hkc = 0.; - double ctEq = 0.; - - if (name == "wake") - { - if (us > 0.99995) - us = 0.99995; - Hkc = Hk - 1; - ctEq = std::sqrt(4 * Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / ((1 - us) * (Hk * Hk) * H)); // Here it is ctEq^0.5 - } - else - { - if (us > 0.95) - us = 0.98; - Hkc = std::max(Hk - 1 - 18 / Ret, 0.01); - ctEq = std::sqrt(Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / ((1 - us) * (Hk * Hk) * H)); // Here it is ctEq^0.5 - } - if (Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / ((1 - us) * (Hk * Hk) * H) < 0) - std::cout << "Negative sqrt encountered " << std::endl; - - closureVars = ctEq; +void Closures::turbulentClosures(double &closureVars, double theta, double H, + double Ct, double Ret, const double Me, + const std::string name) { + H = std::max(H, 1.00005); + Ct = std::min(Ct, 0.3); + + double Hk = (H - 0.29 * Me * Me) / (1 + 0.113 * Me * Me); + if (name == "wake") + Hk = std::max(Hk, 1.00005); + else + Hk = std::max(Hk, 1.05000); + + double H0 = 0.; + if (Ret <= 400) + H0 = 4.0; + else + H0 = 3 + (400 / Ret); + if (Ret <= 200) + Ret = 200; + + double Hstar = 0.; + if (Hk <= H0) + Hstar = + ((0.5 - 4 / Ret) * ((H0 - Hk) / (H0 - 1)) * ((H0 - Hk) / (H0 - 1))) * + (1.5 / (Hk + 0.5)) + + 1.5 + 4 / Ret; + else + Hstar = (Hk - H0) * (Hk - H0) * + (0.007 * std::log(Ret) / + ((Hk - H0 + 4 / std::log(Ret)) * + (Hk - H0 + 4 / std::log(Ret))) + + 0.015 / Hk) + + 1.5 + 4 / Ret; + + // Whitfield's minor additional compressibility correction. + Hstar = (Hstar + 0.028 * Me * Me) / (1 + 0.014 * Me * Me); + + // Equivalent normalized wall slip velocity. + double us = (Hstar / 2) * (1 - 4 * (Hk - 1) / (3 * H)); + + double Ctcon = 0.5 / (6.7 * 6.7 * 0.75); + + double Hkc = 0.; + double ctEq = 0.; + + if (name == "wake") { + if (us > 0.99995) + us = 0.99995; + Hkc = Hk - 1; + ctEq = std::sqrt(4 * Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / + ((1 - us) * (Hk * Hk) * H)); // Here it is ctEq^0.5 + } else { + if (us > 0.95) + us = 0.98; + Hkc = std::max(Hk - 1 - 18 / Ret, 0.01); + ctEq = std::sqrt(Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / + ((1 - us) * (Hk * Hk) * H)); // Here it is ctEq^0.5 + } + if (Hstar * Ctcon * ((Hk - 1) * Hkc * Hkc) / ((1 - us) * (Hk * Hk) * H) < 0) + std::cout << "Negative sqrt encountered " << std::endl; + + closureVars = ctEq; } \ No newline at end of file diff --git a/blast/src/DClosures.h b/blast/src/DClosures.h index a820065..1f3841f 100644 --- a/blast/src/DClosures.h +++ b/blast/src/DClosures.h @@ -2,29 +2,27 @@ #define DCLOSURES_H #include "blast.h" -#include <vector> #include <string> +#include <vector> -namespace blast -{ +namespace blast { /** * @brief Boundary layer closure relations. * @author Paul Dechamps */ -class BLAST_API Closures -{ +class BLAST_API Closures { public: - static void laminarClosures(std::vector<double> &closureVars, double theta, - double H, double Ret, const double Me, + static void laminarClosures(std::vector<double> &closureVars, double theta, + double H, double Ret, const double Me, + const std::string name); + static void turbulentClosures(std::vector<double> &closureVars, double theta, + double H, double Ct, double Ret, double Me, + const std::string name); + static void turbulentClosures(double &closureVars, double theta, double H, + double Ct, double Ret, const double Me, const std::string name); - static void turbulentClosures(std::vector<double> &closureVars, double theta, - double H, double Ct, double Ret, double Me, - const std::string name); - static void turbulentClosures(double &closureVars, double theta, - double H, double Ct, double Ret, const double Me, - const std::string name); }; } // namespace blast #endif // DCLOSURES_H diff --git a/blast/src/DCoupledAdjoint.cpp b/blast/src/DCoupledAdjoint.cpp index 90d440a..2001591 100644 --- a/blast/src/DCoupledAdjoint.cpp +++ b/blast/src/DCoupledAdjoint.cpp @@ -17,374 +17,436 @@ #include "DCoupledAdjoint.h" #include "DDriver.h" #include "wAdjoint.h" -#include "wNewton.h" -#include "wSolver.h" -#include "wProblem.h" #include "wBlowing.h" +#include "wBlowingResidual.h" #include "wFluid.h" #include "wMshData.h" +#include "wNewton.h" #include "wNode.h" -#include "wBlowingResidual.h" +#include "wProblem.h" +#include "wSolver.h" -#include "wLinearSolver.h" -#include "wGmres.h" #include "wCache.h" #include "wGauss.h" +#include "wGmres.h" +#include "wLinearSolver.h" -#include <Eigen/Sparse> -#include<Eigen/SparseLU> #include <Eigen/Dense> -#include<Eigen/SparseCholesky> -#include <fstream> -#include <deque> +#include <Eigen/Sparse> +#include <Eigen/SparseCholesky> +#include <Eigen/SparseLU> #include <algorithm> -#include <iomanip> #include <chrono> +#include <deque> +#include <fstream> +#include <iomanip> using namespace blast; -CoupledAdjoint::CoupledAdjoint(std::shared_ptr<dart::Adjoint> _iadjoint, std::shared_ptr<blast::Driver> vSolver) : iadjoint(_iadjoint), vsol(vSolver) -{ - isol = iadjoint->sol; - // Linear solvers (if GMRES, use the same, but with a thighter tolerance) - if (isol->linsol->type() == tbox::LSolType::GMRES_ILUT) - { - std::shared_ptr<tbox::Gmres> gmres = std::make_shared<tbox::Gmres>(*dynamic_cast<tbox::Gmres *>(isol->linsol.get())); - gmres->setTolerance(1e-8); - alinsol = gmres; - } - else - alinsol = isol->linsol; - - // Initalize all derivatives - this->reset(); +CoupledAdjoint::CoupledAdjoint(std::shared_ptr<dart::Adjoint> _iadjoint, + std::shared_ptr<blast::Driver> vSolver) + : iadjoint(_iadjoint), vsol(vSolver) { + isol = iadjoint->sol; + // Linear solvers (if GMRES, use the same, but with a thighter tolerance) + if (isol->linsol->type() == tbox::LSolType::GMRES_ILUT) { + std::shared_ptr<tbox::Gmres> gmres = std::make_shared<tbox::Gmres>( + *dynamic_cast<tbox::Gmres *>(isol->linsol.get())); + gmres->setTolerance(1e-8); + alinsol = gmres; + } else + alinsol = isol->linsol; + + // Initalize all derivatives + this->reset(); } -void CoupledAdjoint::reset() -{ - size_t nDim = isol->pbl->nDim; // Number of dimensions of the problem - size_t nNd = isol->pbl->msh->nodes.size(); // Number of domain nodes - size_t nNs = 0; - for (auto bBC : isol->pbl->bBCs) - nNs += bBC->nodes.size(); // Number of surface nodes - nNs += 1; // Duplicate stagnation point - size_t nEs = 0; - for (auto bBC : isol->pbl->bBCs) - nEs += bBC->uE.size(); // Number of blowing elements - - dRphi_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNd); - dRM_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNd); - dRrho_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNd); - dRv_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nNd); - dRdStar_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNd); - dRblw_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNd); - - dRphi_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNs); - dRM_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); - dRrho_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); - dRv_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nNs); - dRdStar_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); - dRblw_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNs); - - dRphi_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNs); - dRM_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); - dRrho_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); - dRv_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nNs); - dRdStar_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); - dRblw_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNs); - - dRphi_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nDim*nNs); - dRM_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim*nNs); - dRrho_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim*nNs); - dRv_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nDim*nNs); - dRdStar_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim*nNs); - dRblw_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nDim*nNs); - - dRphi_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNs); - dRM_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); - dRrho_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); - dRv_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nNs); - dRdStar_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); - dRblw_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNs); - - dRphi_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nEs); - dRM_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nEs); - dRrho_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nEs); - dRv_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nEs); - dRdStar_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nEs); - dRblw_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nEs); - - dRphi_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nDim*nNd); - dRM_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim*nNd); - dRrho_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim*nNd); - dRv_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nDim*nNd); - dRdStar_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim*nNd); - dRblw_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nDim*nNd); - - // Gradient wrt objective function - dRphi_AoA = Eigen::VectorXd::Zero(nNd); - - // Objective functions - // Cl = f(phi) & Cd = Cdp + Cdf = f(phi, M, v) - dCl_phi = Eigen::VectorXd::Zero(nNd); - dCd_phi = Eigen::VectorXd::Zero(nNd); - dCd_M = Eigen::VectorXd::Zero(nNs); - dCd_v = Eigen::VectorXd::Zero(nDim*nNs); - dCd_dStar = Eigen::VectorXd::Zero(nNs); - - // Angle of attack - dCl_AoA = 0.0; - dCd_AoA = 0.0; - tdCl_AoA = 0.0; - tdCd_AoA = 0.0; - - // Mesh - dRx_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNd, nDim*nNd); - dCl_x = Eigen::VectorXd::Zero(nDim*nNd); - dCdp_x = Eigen::VectorXd::Zero(nDim*nNd); - dCdf_x = Eigen::VectorXd::Zero(nDim*nNd); - - tdCl_x.resize(nNd, Eigen::Vector3d::Zero()); - tdCd_x.resize(nNd, Eigen::Vector3d::Zero()); +void CoupledAdjoint::reset() { + size_t nDim = isol->pbl->nDim; // Number of dimensions of the problem + size_t nNd = isol->pbl->msh->nodes.size(); // Number of domain nodes + size_t nNs = 0; + for (auto bBC : isol->pbl->bBCs) + nNs += bBC->nodes.size(); // Number of surface nodes + nNs += 1; // Duplicate stagnation point + size_t nEs = 0; + for (auto bBC : isol->pbl->bBCs) + nEs += bBC->uE.size(); // Number of blowing elements + + dRphi_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNd); + dRM_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNd); + dRrho_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNd); + dRv_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim * nNs, nNd); + dRdStar_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNd); + dRblw_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNd); + + dRphi_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNs); + dRM_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRrho_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRv_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim * nNs, nNs); + dRdStar_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRblw_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNs); + + dRphi_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNs); + dRM_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRrho_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRv_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim * nNs, nNs); + dRdStar_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRblw_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNs); + + dRphi_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nDim * nNs); + dRM_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim * nNs); + dRrho_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim * nNs); + dRv_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim * nNs, nDim * nNs); + dRdStar_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim * nNs); + dRblw_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nDim * nNs); + + dRphi_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNs); + dRM_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRrho_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRv_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim * nNs, nNs); + dRdStar_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRblw_dStar = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNs); + + dRphi_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nEs); + dRM_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nEs); + dRrho_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nEs); + dRv_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim * nNs, nEs); + dRdStar_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nEs); + dRblw_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nEs); + + dRphi_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nDim * nNd); + dRM_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim * nNd); + dRrho_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim * nNd); + dRv_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim * nNs, nDim * nNd); + dRdStar_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim * nNd); + dRblw_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nDim * nNd); + + // Gradient wrt objective function + dRphi_AoA = Eigen::VectorXd::Zero(nNd); + + // Objective functions + // Cl = f(phi) & Cd = Cdp + Cdf = f(phi, M, v) + dCl_phi = Eigen::VectorXd::Zero(nNd); + dCd_phi = Eigen::VectorXd::Zero(nNd); + dCd_M = Eigen::VectorXd::Zero(nNs); + dCd_v = Eigen::VectorXd::Zero(nDim * nNs); + dCd_dStar = Eigen::VectorXd::Zero(nNs); + + // Angle of attack + dCl_AoA = 0.0; + dCd_AoA = 0.0; + tdCl_AoA = 0.0; + tdCd_AoA = 0.0; + + // Mesh + dRx_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim * nNd, nDim * nNd); + dCl_x = Eigen::VectorXd::Zero(nDim * nNd); + dCdp_x = Eigen::VectorXd::Zero(nDim * nNd); + dCdf_x = Eigen::VectorXd::Zero(nDim * nNd); + + tdCl_x.resize(nNd, Eigen::Vector3d::Zero()); + tdCd_x.resize(nNd, Eigen::Vector3d::Zero()); } -void CoupledAdjoint::buildAdjointMatrix(std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor>*>> &matrices, Eigen::SparseMatrix<double, Eigen::RowMajor> &matrixAdjoint) -{ - // Create a list of triplets for the larger matrix - std::deque<Eigen::Triplet<double>> triplets; - - // Sanity check - for (size_t irow = 0; irow < matrices.size(); ++irow) - { - if (irow > 0) - if (matrices[irow].size() != matrices[irow-1].size()){ - std::cout << "WRONG ROW SIZE " << std::endl; - throw; - } - for (size_t icol = 0; icol < matrices[irow].size(); ++icol) - if (icol > 0) - if (matrices[irow][icol]->rows() != matrices[irow][icol-1]->rows()){ - std::cout << "WRONG COL SIZE " << std::endl; - throw; - } - } - - // Iterate over the rows and columns of the vector - int rowOffset = 0; - for (const auto& row : matrices) { - int colOffset = 0; - for (const auto& matrix : row) { - // Add the triplets of the matrix to the list of triplets for the larger matrix - for (int k = 0; k < matrix->outerSize(); ++k) { - for (Eigen::SparseMatrix<double, Eigen::RowMajor>::InnerIterator it(*matrix, k); it; ++it) { - triplets.push_back(Eigen::Triplet<double>(it.row() + rowOffset, it.col() + colOffset, it.value())); - } - } - colOffset += matrix->cols(); +void CoupledAdjoint::buildAdjointMatrix( + std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor> *>> + &matrices, + Eigen::SparseMatrix<double, Eigen::RowMajor> &matrixAdjoint) { + // Create a list of triplets for the larger matrix + std::deque<Eigen::Triplet<double>> triplets; + + // Sanity check + for (size_t irow = 0; irow < matrices.size(); ++irow) { + if (irow > 0) + if (matrices[irow].size() != matrices[irow - 1].size()) { + std::cout << "WRONG ROW SIZE " << std::endl; + throw; + } + for (size_t icol = 0; icol < matrices[irow].size(); ++icol) + if (icol > 0) + if (matrices[irow][icol]->rows() != matrices[irow][icol - 1]->rows()) { + std::cout << "WRONG COL SIZE " << std::endl; + throw; } - rowOffset += row[0]->rows(); + } + + // Iterate over the rows and columns of the vector + int rowOffset = 0; + for (const auto &row : matrices) { + int colOffset = 0; + for (const auto &matrix : row) { + // Add the triplets of the matrix to the list of triplets for the larger + // matrix + for (int k = 0; k < matrix->outerSize(); ++k) { + for (Eigen::SparseMatrix<double, Eigen::RowMajor>::InnerIterator it( + *matrix, k); + it; ++it) { + triplets.push_back(Eigen::Triplet<double>( + it.row() + rowOffset, it.col() + colOffset, it.value())); + } + } + colOffset += matrix->cols(); } - // Create a new matrix from the deque of triplets - matrixAdjoint.setFromTriplets(triplets.begin(), triplets.end()); - matrixAdjoint.prune(0.); - matrixAdjoint.makeCompressed(); + rowOffset += row[0]->rows(); + } + // Create a new matrix from the deque of triplets + matrixAdjoint.setFromTriplets(triplets.begin(), triplets.end()); + matrixAdjoint.prune(0.); + matrixAdjoint.makeCompressed(); } -void CoupledAdjoint::run() -{ - tms["0-Total"].start(); - tms["1-Derivatives"].start(); - tms2["1-adj_inviscid"].start(); - gradientswrtInviscidFlow(); - tms2["1-adj_inviscid"].stop(); - tms2["2-adj_mach"].start(); - gradientswrtMachNumber(); - tms2["2-adj_mach"].stop(); - tms2["3-adj_density"].start(); - gradientswrtDensity(); - tms2["3-adj_density"].stop(); - tms2["4-adj_velocity"].start(); - gradientswrtVelocity(); - tms2["4-adj_velocity"].stop(); - tms2["5-adj_dStar"].start(); - gradientswrtDeltaStar(); - tms2["5-adj_dStar"].stop(); - tms2["6-adj_blw"].start(); - gradientswrtBlowingVelocity(); - tms2["6-adj_blw"].stop(); - tms2["7-adj_aoa"].start(); - gradientwrtAoA(); - tms2["7-adj_aoa"].stop(); - tms2["8-adj_mesh"].start(); - gradientwrtMesh(); - tms2["8-adj_mesh"].stop(); - tms["1-Derivatives"].stop(); - - transposeMatrices(); - - tms2["9-build"].start(); - std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor>*>> matrices = { - {&dRphi_phi, &dRM_phi, &dRrho_phi, &dRv_phi, &dRdStar_phi, &dRblw_phi}, - {&dRphi_M, &dRM_M, &dRrho_M, &dRv_M, &dRdStar_M, &dRblw_M}, - {&dRphi_rho, &dRM_rho, &dRrho_rho, &dRv_rho, &dRdStar_rho, &dRblw_rho}, - {&dRphi_v, &dRM_v, &dRrho_v, &dRv_v, &dRdStar_v, &dRblw_v}, - {&dRphi_dStar, &dRM_dStar, &dRrho_dStar, &dRv_dStar, &dRdStar_dStar, &dRblw_dStar}, - {&dRphi_blw, &dRM_blw, &dRrho_blw, &dRv_blw, &dRdStar_blw, &dRblw_blw} - }; - - int rows = 0; int cols = 0; - for (const auto& row : matrices) rows += row[0]->rows(); // All matrices in a row have the same number of rows - for (const auto& mat1 : matrices[0]) cols += mat1->cols(); // All matrices in a column have the same number of columns - Eigen::SparseMatrix<double, Eigen::RowMajor> A_adjoint(rows, cols); - buildAdjointMatrix(matrices, A_adjoint); - tms2["9-build"].stop(); - - size_t phiIdx = 0; - size_t machIdx = dRphi_phi.cols(); - size_t rhoIdx = machIdx + dRM_M.cols(); - size_t vIdx = rhoIdx + dRrho_rho.cols(); - size_t dStarIdx = vIdx + dRv_v.cols(); - size_t blwIdx = dStarIdx + dRdStar_dStar.cols(); - - //**************************************************************************// - // Gradients wrt angle of attack // - //**************************************************************************// - // CL - tms["2-Solve"].start(); - tms2["10-solveCxAoA"].start(); - std::vector<double> rhsCl(A_adjoint.cols(), 0.0); - for (auto i = phiIdx; i<phiIdx+dCl_phi.size(); ++i) - rhsCl[i] = dCl_phi[i]; // Only dCl_dphi is non-zero - Eigen::VectorXd rhsCl_ = Eigen::Map<const Eigen::VectorXd>(rhsCl.data(), rhsCl.size()); - - Eigen::VectorXd lambdaCl(A_adjoint.cols()); // Solution vector for lambdasCl - Eigen::Map<Eigen::VectorXd> lambdaCl_(lambdaCl.data(), lambdaCl.size()); - - alinsol->compute(A_adjoint, Eigen::Map<Eigen::VectorXd>(rhsCl_.data(), rhsCl_.size()), lambdaCl_); - - // Total gradient - tdCl_AoA = dCl_AoA - dRphi_AoA.transpose()*lambdaCl.segment(phiIdx, dRphi_phi.cols()); - - // CD - std::vector<double> rhsCd(A_adjoint.cols(), 0.0); - int jj = 0; - for (auto i = phiIdx; i<phiIdx+dCd_phi.size(); ++i) - { - rhsCd[i] = dCd_phi[jj]; - jj++; - } - jj = 0; - for (auto i = machIdx; i<machIdx+dCd_M.size(); ++i) - { - rhsCd[i] = dCd_M[jj]; - jj++; - } - jj = 0; - for (auto i = vIdx; i<vIdx+dCd_v.size(); ++i) - { - rhsCd[i] = dCd_v[jj]; - jj++; +void CoupledAdjoint::run() { + tms["0-Total"].start(); + tms["1-Derivatives"].start(); + tms2["1-adj_inviscid"].start(); + gradientswrtInviscidFlow(); + tms2["1-adj_inviscid"].stop(); + tms2["2-adj_mach"].start(); + gradientswrtMachNumber(); + tms2["2-adj_mach"].stop(); + tms2["3-adj_density"].start(); + gradientswrtDensity(); + tms2["3-adj_density"].stop(); + tms2["4-adj_velocity"].start(); + gradientswrtVelocity(); + tms2["4-adj_velocity"].stop(); + tms2["5-adj_dStar"].start(); + gradientswrtDeltaStar(); + tms2["5-adj_dStar"].stop(); + tms2["6-adj_blw"].start(); + gradientswrtBlowingVelocity(); + tms2["6-adj_blw"].stop(); + tms2["7-adj_aoa"].start(); + gradientwrtAoA(); + tms2["7-adj_aoa"].stop(); + tms2["8-adj_mesh"].start(); + gradientwrtMesh(); + tms2["8-adj_mesh"].stop(); + tms["1-Derivatives"].stop(); + + transposeMatrices(); + + tms2["9-build"].start(); + std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor> *>> + matrices = {{&dRphi_phi, &dRM_phi, &dRrho_phi, &dRv_phi, &dRdStar_phi, + &dRblw_phi}, + {&dRphi_M, &dRM_M, &dRrho_M, &dRv_M, &dRdStar_M, &dRblw_M}, + {&dRphi_rho, &dRM_rho, &dRrho_rho, &dRv_rho, &dRdStar_rho, + &dRblw_rho}, + {&dRphi_v, &dRM_v, &dRrho_v, &dRv_v, &dRdStar_v, &dRblw_v}, + {&dRphi_dStar, &dRM_dStar, &dRrho_dStar, &dRv_dStar, + &dRdStar_dStar, &dRblw_dStar}, + {&dRphi_blw, &dRM_blw, &dRrho_blw, &dRv_blw, &dRdStar_blw, + &dRblw_blw}}; + + int rows = 0; + int cols = 0; + for (const auto &row : matrices) + rows += + row[0]->rows(); // All matrices in a row have the same number of rows + for (const auto &mat1 : matrices[0]) + cols += mat1->cols(); // All matrices in a column have the same number of + // columns + Eigen::SparseMatrix<double, Eigen::RowMajor> A_adjoint(rows, cols); + buildAdjointMatrix(matrices, A_adjoint); + tms2["9-build"].stop(); + + size_t phiIdx = 0; + size_t machIdx = dRphi_phi.cols(); + size_t rhoIdx = machIdx + dRM_M.cols(); + size_t vIdx = rhoIdx + dRrho_rho.cols(); + size_t dStarIdx = vIdx + dRv_v.cols(); + size_t blwIdx = dStarIdx + dRdStar_dStar.cols(); + + //**************************************************************************// + // Gradients wrt angle of attack // + //**************************************************************************// + // CL + tms["2-Solve"].start(); + tms2["10-solveCxAoA"].start(); + std::vector<double> rhsCl(A_adjoint.cols(), 0.0); + for (auto i = phiIdx; i < phiIdx + dCl_phi.size(); ++i) + rhsCl[i] = dCl_phi[i]; // Only dCl_dphi is non-zero + Eigen::VectorXd rhsCl_ = + Eigen::Map<const Eigen::VectorXd>(rhsCl.data(), rhsCl.size()); + + Eigen::VectorXd lambdaCl(A_adjoint.cols()); // Solution vector for lambdasCl + Eigen::Map<Eigen::VectorXd> lambdaCl_(lambdaCl.data(), lambdaCl.size()); + + alinsol->compute(A_adjoint, + Eigen::Map<Eigen::VectorXd>(rhsCl_.data(), rhsCl_.size()), + lambdaCl_); + + // Total gradient + tdCl_AoA = dCl_AoA - + dRphi_AoA.transpose() * lambdaCl.segment(phiIdx, dRphi_phi.cols()); + + // CD + std::vector<double> rhsCd(A_adjoint.cols(), 0.0); + int jj = 0; + for (auto i = phiIdx; i < phiIdx + dCd_phi.size(); ++i) { + rhsCd[i] = dCd_phi[jj]; + jj++; + } + jj = 0; + for (auto i = machIdx; i < machIdx + dCd_M.size(); ++i) { + rhsCd[i] = dCd_M[jj]; + jj++; + } + jj = 0; + for (auto i = vIdx; i < vIdx + dCd_v.size(); ++i) { + rhsCd[i] = dCd_v[jj]; + jj++; + } + jj = 0; + for (auto i = dStarIdx; i < dStarIdx + dCd_dStar.size(); ++i) { + rhsCd[i] = dCd_dStar[jj]; + jj++; + } + Eigen::VectorXd rhsCd_ = + Eigen::Map<const Eigen::VectorXd>(rhsCd.data(), rhsCd.size()); + + Eigen::VectorXd lambdaCd(A_adjoint.cols()); // Solution vector for lambdasCd + Eigen::Map<Eigen::VectorXd> lambdaCd_(lambdaCd.data(), lambdaCd.size()); + + alinsol->compute(A_adjoint, + Eigen::Map<Eigen::VectorXd>(rhsCd_.data(), rhsCd_.size()), + lambdaCd_); + + // Total gradient + tdCd_AoA = dCd_AoA - + dRphi_AoA.transpose() * + lambdaCd.segment(phiIdx, dRphi_phi.cols()); // Total gradient + tms2["10-solveCxAoA"].stop(); + + //**************************************************************************// + // Gradients wrt mesh coordinates // + //--------------------------------------------------------------------------// + // Ck (cL, cd) // + // Solution lambdaCl_x of (from augmented Lagrangian, eqn d/dx ) // + // "dCk_x + dRphi_x * lambdaCk_phi + dRdStar_x * lambdaCk_x // + // + dRblw_x * lambdaCk_blw + dRx_x * lambdaCk_x = 0" // + //**************************************************************************// + + tms2["12-solveCxMesh"].start(); + Eigen::VectorXd rhsCl_x = dCl_x; + rhsCl_x -= + dRphi_x.transpose() * + lambdaCl.segment(phiIdx, dRphi_phi.cols()); // Potential contribution + rhsCl_x -= + dRM_x.transpose() * + lambdaCl.segment(machIdx, dRM_M.cols()); // Mach number contribution + rhsCl_x -= dRrho_x.transpose() * + lambdaCl.segment(rhoIdx, dRrho_rho.cols()); // Density contribution + rhsCl_x -= dRv_x.transpose() * + lambdaCl.segment(vIdx, dRv_v.cols()); // Velocity contribution + rhsCl_x -= dRdStar_x.transpose() * + lambdaCl.segment( + dStarIdx, + dRdStar_dStar.cols()); // Displacement thickness contribution + rhsCl_x -= dRblw_x.transpose() * + lambdaCl.segment(blwIdx, dRblw_blw.cols()); // Blowing contribution + + Eigen::VectorXd lambdaCl_x = + Eigen::VectorXd::Zero(isol->pbl->nDim * isol->pbl->msh->nodes.size()); + Eigen::Map<Eigen::VectorXd> lambdaCl_x_(lambdaCl_x.data(), lambdaCl_x.size()); + alinsol->compute(dRx_x.transpose(), + Eigen::Map<Eigen::VectorXd>(rhsCl_x.data(), rhsCl_x.size()), + lambdaCl_x_); + + Eigen::VectorXd rhsCd_x = dCdp_x; // Pressure drag coefficient contribution + rhsCd_x += dCdf_x; // Friction drag coefficient contribution + rhsCd_x -= + dRphi_x.transpose() * + lambdaCd.segment(phiIdx, dRphi_phi.cols()); // Potential contribution + rhsCd_x -= + dRM_x.transpose() * + lambdaCd.segment(machIdx, dRM_M.cols()); // Mach number contribution + rhsCd_x -= dRrho_x.transpose() * + lambdaCd.segment(rhoIdx, dRrho_rho.cols()); // Density contribution + rhsCd_x -= dRv_x.transpose() * + lambdaCd.segment(vIdx, dRv_v.cols()); // Velocity contribution + rhsCd_x -= dRdStar_x.transpose() * + lambdaCd.segment( + dStarIdx, + dRdStar_dStar.cols()); // Displacement thickness contribution + rhsCd_x -= dRblw_x.transpose() * + lambdaCd.segment(blwIdx, dRblw_blw.cols()); // Blowing contribution + + Eigen::VectorXd lambdaCd_x = + Eigen::VectorXd::Zero(isol->pbl->nDim * isol->pbl->msh->nodes.size()); + Eigen::Map<Eigen::VectorXd> lambdaCd_x_(lambdaCd_x.data(), lambdaCd_x.size()); + alinsol->compute(dRx_x.transpose(), + Eigen::Map<Eigen::VectorXd>(rhsCd_x.data(), rhsCd_x.size()), + lambdaCd_x_); + + for (auto n : isol->pbl->msh->nodes) { + for (int m = 0; m < isol->pbl->nDim; m++) { + tdCl_x[n->row](m) = lambdaCl_x[isol->pbl->nDim * (n->row) + m]; + tdCd_x[n->row](m) = lambdaCd_x[isol->pbl->nDim * (n->row) + m]; } - jj = 0; - for (auto i = dStarIdx; i<dStarIdx+dCd_dStar.size(); ++i) - { - rhsCd[i] = dCd_dStar[jj]; - jj++; - } - Eigen::VectorXd rhsCd_ = Eigen::Map<const Eigen::VectorXd>(rhsCd.data(), rhsCd.size()); - - Eigen::VectorXd lambdaCd(A_adjoint.cols()); // Solution vector for lambdasCd - Eigen::Map<Eigen::VectorXd> lambdaCd_(lambdaCd.data(), lambdaCd.size()); - - alinsol->compute(A_adjoint, Eigen::Map<Eigen::VectorXd>(rhsCd_.data(), rhsCd_.size()), lambdaCd_); - - // Total gradient - tdCd_AoA = dCd_AoA - dRphi_AoA.transpose()*lambdaCd.segment(phiIdx, dRphi_phi.cols()); // Total gradient - tms2["10-solveCxAoA"].stop(); - - //**************************************************************************// - // Gradients wrt mesh coordinates // - //--------------------------------------------------------------------------// - // Ck (cL, cd) // - // Solution lambdaCl_x of (from augmented Lagrangian, eqn d/dx ) // - // "dCk_x + dRphi_x * lambdaCk_phi + dRdStar_x * lambdaCk_x // - // + dRblw_x * lambdaCk_blw + dRx_x * lambdaCk_x = 0" // - //**************************************************************************// - - tms2["12-solveCxMesh"].start(); - Eigen::VectorXd rhsCl_x = dCl_x; - rhsCl_x -= dRphi_x.transpose() * lambdaCl.segment(phiIdx, dRphi_phi.cols()); // Potential contribution - rhsCl_x -= dRM_x.transpose() * lambdaCl.segment(machIdx, dRM_M.cols()); // Mach number contribution - rhsCl_x -= dRrho_x.transpose() * lambdaCl.segment(rhoIdx, dRrho_rho.cols()); // Density contribution - rhsCl_x -= dRv_x.transpose() * lambdaCl.segment(vIdx, dRv_v.cols()); // Velocity contribution - rhsCl_x -= dRdStar_x.transpose() * lambdaCl.segment(dStarIdx, dRdStar_dStar.cols()); // Displacement thickness contribution - rhsCl_x -= dRblw_x.transpose() * lambdaCl.segment(blwIdx, dRblw_blw.cols()); // Blowing contribution - - Eigen::VectorXd lambdaCl_x = Eigen::VectorXd::Zero(isol->pbl->nDim * isol->pbl->msh->nodes.size()); - Eigen::Map<Eigen::VectorXd> lambdaCl_x_(lambdaCl_x.data(), lambdaCl_x.size()); - alinsol->compute(dRx_x.transpose(), Eigen::Map<Eigen::VectorXd>(rhsCl_x.data(), rhsCl_x.size()), lambdaCl_x_); - - Eigen::VectorXd rhsCd_x = dCdp_x; // Pressure drag coefficient contribution - rhsCd_x += dCdf_x; // Friction drag coefficient contribution - rhsCd_x -= dRphi_x.transpose() * lambdaCd.segment(phiIdx, dRphi_phi.cols()); // Potential contribution - rhsCd_x -= dRM_x.transpose() * lambdaCd.segment(machIdx, dRM_M.cols()); // Mach number contribution - rhsCd_x -= dRrho_x.transpose() * lambdaCd.segment(rhoIdx, dRrho_rho.cols()); // Density contribution - rhsCd_x -= dRv_x.transpose() * lambdaCd.segment(vIdx, dRv_v.cols()); // Velocity contribution - rhsCd_x -= dRdStar_x.transpose() * lambdaCd.segment(dStarIdx, dRdStar_dStar.cols()); // Displacement thickness contribution - rhsCd_x -= dRblw_x.transpose() * lambdaCd.segment(blwIdx, dRblw_blw.cols()); // Blowing contribution - - Eigen::VectorXd lambdaCd_x = Eigen::VectorXd::Zero(isol->pbl->nDim * isol->pbl->msh->nodes.size()); - Eigen::Map<Eigen::VectorXd> lambdaCd_x_(lambdaCd_x.data(), lambdaCd_x.size()); - alinsol->compute(dRx_x.transpose(), Eigen::Map<Eigen::VectorXd>(rhsCd_x.data(), rhsCd_x.size()), lambdaCd_x_); - - for (auto n : isol->pbl->msh->nodes) - { - for (int m = 0; m < isol->pbl->nDim; m++) - { - tdCl_x[n->row](m) = lambdaCl_x[isol->pbl->nDim * (n->row) + m]; - tdCd_x[n->row](m) = lambdaCd_x[isol->pbl->nDim * (n->row) + m]; - } - } - tms2["12-solveCxMesh"].stop(); - tms["2-Solve"].stop(); - - // Print output - std::cout << "-------------- Adjoint solution --------------" << std::endl; - // aoa gradients - std::cout << std::setw(15) << std::left << "Adjoint AoA" - << std::setw(15) << std::right << "Res[Cl_AoA]" - << std::setw(15) << std::right << "Res[Cd_AoA]" << std::endl; - std::cout << std::fixed << std::setprecision(5); - std::cout << std::setw(15) << std::left << "" - << std::setw(15) << std::right << log10((A_adjoint * Eigen::Map<Eigen::VectorXd>(lambdaCl.data(), lambdaCl.size()) - Eigen::Map<Eigen::VectorXd>(rhsCl.data(), rhsCl.size())).norm()) - << std::setw(15) << std::right << log10((A_adjoint * Eigen::Map<Eigen::VectorXd>(lambdaCd.data(), lambdaCd.size()) - Eigen::Map<Eigen::VectorXd>(rhsCd.data(), rhsCd.size())).norm()) << std::endl; - std::cout << std::setw(15) << std::left << "AoA gradients" - << std::setw(15) << std::right << "dCl_dAoA" - << std::setw(15) << std::right << "dCd_dAoA" << std::endl; - std::cout << std::fixed << std::setprecision(5); - std::cout << std::setw(15) << std::left << "" - << std::setw(15) << std::right << tdCl_AoA - << std::setw(15) << std::right << tdCd_AoA << std::endl; - // mesh gradients - std::cout << std::setw(15) << std::left << "Adjoint mesh" - << std::setw(15) << std::right << "Res[Cl_x]" - << std::setw(15) << std::right << "Res[Cd_x]" << std::endl; - std::cout << std::fixed << std::setprecision(5); - std::cout << std::setw(15) << std::left << "" - << std::setw(15) << std::right << log10((dRx_x.transpose() * Eigen::Map<Eigen::VectorXd>(lambdaCl_x.data(), lambdaCl_x.size()) - Eigen::Map<Eigen::VectorXd>(rhsCl_x.data(), rhsCl_x.size())).norm()) - << std::setw(15) << std::right << log10((dRx_x.transpose() * Eigen::Map<Eigen::VectorXd>(lambdaCd_x.data(), lambdaCd_x.size()) - Eigen::Map<Eigen::VectorXd>(rhsCd_x.data(), rhsCd_x.size())).norm()) << std::endl; - std::cout << std::setw(15) << std::left << "Mesh gradients" - << std::setw(15) << std::right << "Norm[dCl_dX]" - << std::setw(15) << std::right << "Norm[dCd_dX]" << std::endl; - std::cout << std::fixed << std::setprecision(5); - std::cout << std::setw(15) << std::left << "" - << std::setw(15) << std::right << Eigen::Map<Eigen::VectorXd>(lambdaCl_x.data(), lambdaCl_x.size()).norm() - << std::setw(15) << std::right << Eigen::Map<Eigen::VectorXd>(lambdaCd_x.data(), lambdaCd_x.size()).norm() << std::endl; - tms["0-Total"].stop(); - std::cout << "--------------- Adjoint timers ---------------" << std::endl; - std::cout << tms << "----------------------------------------------" << std::endl; - if (vsol->verbose > 2) - std::cout << tms2 << "----------------------------------------------" << std::endl; + } + tms2["12-solveCxMesh"].stop(); + tms["2-Solve"].stop(); + + // Print output + std::cout << "-------------- Adjoint solution --------------" << std::endl; + // aoa gradients + std::cout << std::setw(15) << std::left << "Adjoint AoA" << std::setw(15) + << std::right << "Res[Cl_AoA]" << std::setw(15) << std::right + << "Res[Cd_AoA]" << std::endl; + std::cout << std::fixed << std::setprecision(5); + std::cout << std::setw(15) << std::left << "" << std::setw(15) << std::right + << log10((A_adjoint * Eigen::Map<Eigen::VectorXd>(lambdaCl.data(), + lambdaCl.size()) - + Eigen::Map<Eigen::VectorXd>(rhsCl.data(), rhsCl.size())) + .norm()) + << std::setw(15) << std::right + << log10((A_adjoint * Eigen::Map<Eigen::VectorXd>(lambdaCd.data(), + lambdaCd.size()) - + Eigen::Map<Eigen::VectorXd>(rhsCd.data(), rhsCd.size())) + .norm()) + << std::endl; + std::cout << std::setw(15) << std::left << "AoA gradients" << std::setw(15) + << std::right << "dCl_dAoA" << std::setw(15) << std::right + << "dCd_dAoA" << std::endl; + std::cout << std::fixed << std::setprecision(5); + std::cout << std::setw(15) << std::left << "" << std::setw(15) << std::right + << tdCl_AoA << std::setw(15) << std::right << tdCd_AoA << std::endl; + // mesh gradients + std::cout << std::setw(15) << std::left << "Adjoint mesh" << std::setw(15) + << std::right << "Res[Cl_x]" << std::setw(15) << std::right + << "Res[Cd_x]" << std::endl; + std::cout << std::fixed << std::setprecision(5); + std::cout + << std::setw(15) << std::left << "" << std::setw(15) << std::right + << log10((dRx_x.transpose() * Eigen::Map<Eigen::VectorXd>( + lambdaCl_x.data(), lambdaCl_x.size()) - + Eigen::Map<Eigen::VectorXd>(rhsCl_x.data(), rhsCl_x.size())) + .norm()) + << std::setw(15) << std::right + << log10((dRx_x.transpose() * Eigen::Map<Eigen::VectorXd>( + lambdaCd_x.data(), lambdaCd_x.size()) - + Eigen::Map<Eigen::VectorXd>(rhsCd_x.data(), rhsCd_x.size())) + .norm()) + << std::endl; + std::cout << std::setw(15) << std::left << "Mesh gradients" << std::setw(15) + << std::right << "Norm[dCl_dX]" << std::setw(15) << std::right + << "Norm[dCd_dX]" << std::endl; + std::cout << std::fixed << std::setprecision(5); + std::cout << std::setw(15) << std::left << "" << std::setw(15) << std::right + << Eigen::Map<Eigen::VectorXd>(lambdaCl_x.data(), lambdaCl_x.size()) + .norm() + << std::setw(15) << std::right + << Eigen::Map<Eigen::VectorXd>(lambdaCd_x.data(), lambdaCd_x.size()) + .norm() + << std::endl; + tms["0-Total"].stop(); + std::cout << "--------------- Adjoint timers ---------------" << std::endl; + std::cout << tms << "----------------------------------------------" + << std::endl; + if (vsol->verbose > 2) + std::cout << tms2 << "----------------------------------------------" + << std::endl; } /** @@ -392,72 +454,80 @@ void CoupledAdjoint::run() * Non-zero are: dRphi_phi, dRM_phi, dRrho_phi, dRv_phi * Zeros are: dRdStar_phi, dRblw_phi, dRx_phi */ -void CoupledAdjoint::gradientswrtInviscidFlow() -{ - //**************************************************************************// - // dRphi_phi // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - dRphi_phi = iadjoint->getRu_U(); - - //**************************************************************************// - // dRM_phi, dRrho_phi, dRv_phi // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - auto pbl = isol->pbl; - - std::deque<Eigen::Triplet<double>> T_dM; - std::deque<Eigen::Triplet<double>> T_drho; - std::deque<Eigen::Triplet<double>> T_dv; - - size_t jj = 0; - int iReg = 0; - for (auto sec : vsol->sections[0]) - { - if (sec->name == "wake") - iReg = 1; - else if (sec->name == "upper" || sec->name == "lower") - iReg = 0; - else - throw std::runtime_error("gradientswrtInviscidFlow: Unknown section name"); - for (size_t iNode = 0; iNode < sec->nNodes; ++iNode) - { - tbox::Node* srfNode = pbl->bBCs[iReg]->nodes[sec->rows[iNode]]; - double nAdjElms = static_cast<double>(pbl->fluid->neMap[srfNode].size()); - for (auto e: pbl->fluid->neMap[srfNode]) - { - // dv/dphi = dv/dgradPhi * dgradPhi/dphi = dgradPhi/dphi = d(gradN_k phi_k) / dphi_j - // dM/dphi = dM/dgradPhi * dgradPhi/dphi = dM/dgradPhi * dv/dphi - // drho/dphi = drho/dgradPhi * dgradPhi/dphi = drho/dgradPhi * dv/dphi - Eigen::MatrixXd gradV = e->getJinv(0) * e->getVCache().getDsf(0); - Eigen::VectorXd gradM = isol->pbl->fluid->mach->evalGrad(*e, isol->phi, 0) * e->computeGradient(isol->phi, 0).transpose() * gradV; - Eigen::VectorXd gradrho = isol->pbl->fluid->rho->evalGrad(*e, isol->phi, 0) * e->computeGradient(isol->phi, 0).transpose() * gradV; - for (size_t k = 0; k < e->nodes.size(); ++k) - { - T_dM.push_back(Eigen::Triplet<double>(jj, e->nodes[k]->row, -gradM(k)/nAdjElms)); - T_drho.push_back(Eigen::Triplet<double>(jj, e->nodes[k]->row, -gradrho(k)/nAdjElms)); - for (int idim = 0; idim < pbl->nDim; ++idim) - T_dv.push_back(Eigen::Triplet<double>(jj*pbl->nDim + idim, e->nodes[k]->row, -gradV(k*pbl->nDim + idim)/nAdjElms)); - } - } - ++jj; +void CoupledAdjoint::gradientswrtInviscidFlow() { + //**************************************************************************// + // dRphi_phi // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + dRphi_phi = iadjoint->getRu_U(); + + //**************************************************************************// + // dRM_phi, dRrho_phi, dRv_phi // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + auto pbl = isol->pbl; + + std::deque<Eigen::Triplet<double>> T_dM; + std::deque<Eigen::Triplet<double>> T_drho; + std::deque<Eigen::Triplet<double>> T_dv; + + size_t jj = 0; + int iReg = 0; + for (auto sec : vsol->sections[0]) { + if (sec->name == "wake") + iReg = 1; + else if (sec->name == "upper" || sec->name == "lower") + iReg = 0; + else + throw std::runtime_error( + "gradientswrtInviscidFlow: Unknown section name"); + for (size_t iNode = 0; iNode < sec->nNodes; ++iNode) { + tbox::Node *srfNode = pbl->bBCs[iReg]->nodes[sec->rows[iNode]]; + double nAdjElms = static_cast<double>(pbl->fluid->neMap[srfNode].size()); + for (auto e : pbl->fluid->neMap[srfNode]) { + // dv/dphi = dv/dgradPhi * dgradPhi/dphi = dgradPhi/dphi = d(gradN_k + // phi_k) / dphi_j dM/dphi = dM/dgradPhi * dgradPhi/dphi = dM/dgradPhi * + // dv/dphi drho/dphi = drho/dgradPhi * dgradPhi/dphi = drho/dgradPhi * + // dv/dphi + Eigen::MatrixXd gradV = e->getJinv(0) * e->getVCache().getDsf(0); + Eigen::VectorXd gradM = + isol->pbl->fluid->mach->evalGrad(*e, isol->phi, 0) * + e->computeGradient(isol->phi, 0).transpose() * gradV; + Eigen::VectorXd gradrho = + isol->pbl->fluid->rho->evalGrad(*e, isol->phi, 0) * + e->computeGradient(isol->phi, 0).transpose() * gradV; + for (size_t k = 0; k < e->nodes.size(); ++k) { + T_dM.push_back(Eigen::Triplet<double>(jj, e->nodes[k]->row, + -gradM(k) / nAdjElms)); + T_drho.push_back(Eigen::Triplet<double>(jj, e->nodes[k]->row, + -gradrho(k) / nAdjElms)); + for (int idim = 0; idim < pbl->nDim; ++idim) + T_dv.push_back(Eigen::Triplet<double>( + jj * pbl->nDim + idim, e->nodes[k]->row, + -gradV(k * pbl->nDim + idim) / nAdjElms)); } + } + ++jj; } - dRM_phi.setFromTriplets(T_dM.begin(), T_dM.end()); - dRrho_phi.setFromTriplets(T_drho.begin(), T_drho.end()); - dRv_phi.setFromTriplets(T_dv.begin(), T_dv.end()); - dRM_phi.prune(0.); dRrho_phi.prune(0.); dRv_phi.prune(0.); - - //**************************************************************************// - // dCl_phi, dCd_phi // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - std::vector<std::vector<double>> dCx_phi = iadjoint->computeGradientCoefficientsFlow(); - dCl_phi = Eigen::VectorXd::Map(dCx_phi[0].data(), dCx_phi[0].size()); - dCd_phi = Eigen::VectorXd::Map(dCx_phi[1].data(), dCx_phi[1].size()); + } + dRM_phi.setFromTriplets(T_dM.begin(), T_dM.end()); + dRrho_phi.setFromTriplets(T_drho.begin(), T_drho.end()); + dRv_phi.setFromTriplets(T_dv.begin(), T_dv.end()); + dRM_phi.prune(0.); + dRrho_phi.prune(0.); + dRv_phi.prune(0.); + + //**************************************************************************// + // dCl_phi, dCd_phi // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + std::vector<std::vector<double>> dCx_phi = + iadjoint->computeGradientCoefficientsFlow(); + dCl_phi = Eigen::VectorXd::Map(dCx_phi[0].data(), dCx_phi[0].size()); + dCd_phi = Eigen::VectorXd::Map(dCx_phi[1].data(), dCx_phi[1].size()); } /** @@ -465,46 +535,46 @@ void CoupledAdjoint::gradientswrtInviscidFlow() * Non-zero are: dRM_M, dRdStar_M * Zeros are: dRphi_M, dRrho_M, dRv_M, dRblw_M, dRx_M */ -void CoupledAdjoint::gradientswrtMachNumber() -{ - //**************************************************************************// - // dRM_M // - //**************************************************************************// - dRM_M.setIdentity(); - - //**************************************************************************// - // dRdStar_M // - //--------------------------------------------------------------------------// - // Central finite-difference // - //**************************************************************************// - std::deque<Eigen::Triplet<double>> T; - double delta = 1e-6; - size_t i = 0; - double saveM = 0.; - std::vector<Eigen::VectorXd> ddStar(2, Eigen::VectorXd::Zero(dRdStar_M.cols())); - std::vector<double> dCdf(2, 0.); - for (auto sec: vsol->sections[0]) - for (size_t j = 0; j < sec->nNodes; ++j) - { - saveM = sec->Me[j]; - - sec->Me[j] = saveM + delta; - ddStar[0] = this->runViscous(); - dCdf[0] = vsol->Cdf; - sec->Me[j] = saveM - delta; - ddStar[1] = this->runViscous(); - dCdf[1] = vsol->Cdf; - - sec->Me[j] = saveM; - - for (int k = 0; k < ddStar[0].size(); ++k) - T.push_back(Eigen::Triplet<double>(k, i, -(ddStar[0][k] - ddStar[1][k])/(2.*delta))); - // Collect Cd gradients - dCd_M(i) = (dCdf[0] - dCdf[1])/(2.*delta); - ++i; - } - dRdStar_M.setFromTriplets(T.begin(), T.end()); - dRdStar_M.prune(0.); +void CoupledAdjoint::gradientswrtMachNumber() { + //**************************************************************************// + // dRM_M // + //**************************************************************************// + dRM_M.setIdentity(); + + //**************************************************************************// + // dRdStar_M // + //--------------------------------------------------------------------------// + // Central finite-difference // + //**************************************************************************// + std::deque<Eigen::Triplet<double>> T; + double delta = 1e-6; + size_t i = 0; + double saveM = 0.; + std::vector<Eigen::VectorXd> ddStar(2, + Eigen::VectorXd::Zero(dRdStar_M.cols())); + std::vector<double> dCdf(2, 0.); + for (auto sec : vsol->sections[0]) + for (size_t j = 0; j < sec->nNodes; ++j) { + saveM = sec->Me[j]; + + sec->Me[j] = saveM + delta; + ddStar[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; + sec->Me[j] = saveM - delta; + ddStar[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; + + sec->Me[j] = saveM; + + for (int k = 0; k < ddStar[0].size(); ++k) + T.push_back(Eigen::Triplet<double>( + k, i, -(ddStar[0][k] - ddStar[1][k]) / (2. * delta))); + // Collect Cd gradients + dCd_M(i) = (dCdf[0] - dCdf[1]) / (2. * delta); + ++i; + } + dRdStar_M.setFromTriplets(T.begin(), T.end()); + dRdStar_M.prune(0.); } /** @@ -512,40 +582,39 @@ void CoupledAdjoint::gradientswrtMachNumber() * Non-zero are: dRrho_rho, dRblw_rho * Zeros are: dRphi_rho, dRM_rho, dRv_rho, dRdStar_rho, dRx_rho */ -void CoupledAdjoint::gradientswrtDensity() -{ - size_t nNs = 0; - for (auto bBC : isol->pbl->bBCs) - nNs += bBC->nodes.size(); // Number of surface nodes - nNs += 1; // Duplicate stagnation point - size_t nEs = 0; - for (auto bBC : isol->pbl->bBCs) - nEs += bBC->uE.size(); // Number of blowing elements - - //**************************************************************************// - // dRrho_rho // - //**************************************************************************// - dRrho_rho.setIdentity(); - - //**************************************************************************// - // dRblw_rho // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - std::deque<Eigen::Triplet<double>> T_blw; - int offSetElms = 0; - int offSetNodes = 0; - for (const auto& sec: vsol->sections[0]) - { - std::vector<std::vector<double>> grad = sec->evalGradwrtRho(); - for (size_t i = 0; i < grad.size(); ++i) - for (size_t j = 0; j < grad[i].size(); ++j) - T_blw.push_back(Eigen::Triplet<double>(i + offSetElms, j + offSetNodes, -grad[i][j])); - offSetElms += sec->nElms; - offSetNodes += sec->nNodes; - } - dRblw_rho.setFromTriplets(T_blw.begin(), T_blw.end()); - dRblw_rho.prune(0.); +void CoupledAdjoint::gradientswrtDensity() { + size_t nNs = 0; + for (auto bBC : isol->pbl->bBCs) + nNs += bBC->nodes.size(); // Number of surface nodes + nNs += 1; // Duplicate stagnation point + size_t nEs = 0; + for (auto bBC : isol->pbl->bBCs) + nEs += bBC->uE.size(); // Number of blowing elements + + //**************************************************************************// + // dRrho_rho // + //**************************************************************************// + dRrho_rho.setIdentity(); + + //**************************************************************************// + // dRblw_rho // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + std::deque<Eigen::Triplet<double>> T_blw; + int offSetElms = 0; + int offSetNodes = 0; + for (const auto &sec : vsol->sections[0]) { + std::vector<std::vector<double>> grad = sec->evalGradwrtRho(); + for (size_t i = 0; i < grad.size(); ++i) + for (size_t j = 0; j < grad[i].size(); ++j) + T_blw.push_back(Eigen::Triplet<double>(i + offSetElms, j + offSetNodes, + -grad[i][j])); + offSetElms += sec->nElms; + offSetNodes += sec->nNodes; + } + dRblw_rho.setFromTriplets(T_blw.begin(), T_blw.end()); + dRblw_rho.prune(0.); } /** @@ -553,201 +622,205 @@ void CoupledAdjoint::gradientswrtDensity() * Non-zeros are: dRv_v, dRdStar_v, dRblw_v * Zeros are: dRphi_v, dRM_v, dRrho_v, dRx_v */ -void CoupledAdjoint::gradientswrtVelocity() -{ - size_t nDim = isol->pbl->nDim; // Number of dimensions of the problem - size_t nNs = 0; - for (auto bBC : isol->pbl->bBCs) - nNs += bBC->nodes.size(); // Number of surface nodes - nNs += 1; // Duplicate stagnation point - size_t nEs = 0; - for (auto bBC : isol->pbl->bBCs) - nEs += bBC->uE.size(); // Number of blowing elements - - //**************************************************************************// - // dRv_v // - //**************************************************************************// - dRv_v.setIdentity(); - - //**** Get velocity****/ - Eigen::MatrixXd v = Eigen::MatrixXd::Zero(nNs, nDim); - size_t i = 0; - int iReg = -1; - for (const auto &sec: vsol->sections[0]) - { - if (sec->name == "wake") - iReg = 1; - else if (sec->name == "upper" || sec->name == "lower") - iReg = 0; - else - throw std::runtime_error("Unknown section name"); - for (size_t j = 0; j < sec->nNodes; ++j) - { - for (size_t idim = 0; idim < nDim; ++idim) - v(i, idim) = isol->U[isol->pbl->bBCs[iReg]->nodes[sec->rows[j]]->row](idim); - ++i; - } +void CoupledAdjoint::gradientswrtVelocity() { + size_t nDim = isol->pbl->nDim; // Number of dimensions of the problem + size_t nNs = 0; + for (auto bBC : isol->pbl->bBCs) + nNs += bBC->nodes.size(); // Number of surface nodes + nNs += 1; // Duplicate stagnation point + size_t nEs = 0; + for (auto bBC : isol->pbl->bBCs) + nEs += bBC->uE.size(); // Number of blowing elements + + //**************************************************************************// + // dRv_v // + //**************************************************************************// + dRv_v.setIdentity(); + + //**** Get velocity****/ + Eigen::MatrixXd v = Eigen::MatrixXd::Zero(nNs, nDim); + size_t i = 0; + int iReg = -1; + for (const auto &sec : vsol->sections[0]) { + if (sec->name == "wake") + iReg = 1; + else if (sec->name == "upper" || sec->name == "lower") + iReg = 0; + else + throw std::runtime_error("Unknown section name"); + for (size_t j = 0; j < sec->nNodes; ++j) { + for (size_t idim = 0; idim < nDim; ++idim) + v(i, idim) = + isol->U[isol->pbl->bBCs[iReg]->nodes[sec->rows[j]]->row](idim); + ++i; } - - //**************************************************************************// - // dvt_v // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - Eigen::SparseMatrix<double, Eigen::RowMajor> dVt_v(nNs, nNs * nDim); - std::deque<Eigen::Triplet<double>> T_vt; - - i = 0; - for (const auto& sec : vsol->sections[0]) { - for (size_t j = 0; j < sec->nNodes; ++j) { - for (size_t idim = 0; idim < nDim; ++idim) { - T_vt.push_back(Eigen::Triplet<double>(i, i * nDim + idim, 1 / std::sqrt(v(i, 0) * v(i, 0) + v(i, 1) * v(i, 1)) * v(i, idim))); - } - ++i; - } + } + + //**************************************************************************// + // dvt_v // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + Eigen::SparseMatrix<double, Eigen::RowMajor> dVt_v(nNs, nNs * nDim); + std::deque<Eigen::Triplet<double>> T_vt; + + i = 0; + for (const auto &sec : vsol->sections[0]) { + for (size_t j = 0; j < sec->nNodes; ++j) { + for (size_t idim = 0; idim < nDim; ++idim) { + T_vt.push_back(Eigen::Triplet<double>( + i, i * nDim + idim, + 1 / std::sqrt(v(i, 0) * v(i, 0) + v(i, 1) * v(i, 1)) * v(i, idim))); + } + ++i; } - dVt_v.setFromTriplets(T_vt.begin(), T_vt.end()); - dVt_v.prune(0.); - - //**************************************************************************// - // dRdStar_vt // - //--------------------------------------------------------------------------// - // Central finite-difference // - //**************************************************************************// - std::deque<Eigen::Triplet<double>> T; - double delta = 1e-6; - i = 0; - double saveM = 0.; - std::vector<Eigen::VectorXd> dvt(2, Eigen::VectorXd::Zero(dRdStar_M.cols())); - std::vector<double> dCdf(2, 0.); - Eigen::VectorXd dCd_vt = Eigen::VectorXd::Zero(dRM_M.cols()); - for (auto sec: vsol->sections[0]) - for (size_t j = 0; j < sec->nNodes; ++j) - { - saveM = sec->vt[j]; - - sec->vt[j] = saveM + delta; - dvt[0] = this->runViscous(); - dCdf[0] = vsol->Cdf; - sec->vt[j] = saveM - delta; - dvt[1] = this->runViscous(); - dCdf[1] = vsol->Cdf; - - sec->vt[j] = saveM; - - for (int k = 0; k < dvt[0].size(); ++k) - T.push_back(Eigen::Triplet<double>(k, i, -(dvt[0][k] - dvt[1][k])/(2.*delta))); - dCd_vt(i) = (dCdf[0] - dCdf[1])/(2.*delta); - ++i; - } - Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_vt(dRdStar_M.rows(), dRdStar_M.cols()); - dRdStar_vt.setFromTriplets(T.begin(), T.end()); - dRdStar_vt.prune(0.); - - //**************************************************************************// - // dRdStar_v // - //**************************************************************************// - dRdStar_v = dRdStar_vt * dVt_v; - dRdStar_v.prune(0.); - - //**************************************************************************// - // dCdf_v // - //**************************************************************************// - dCd_v = dCd_vt.transpose() * dVt_v; // [1xnNs] x [nNs x nNs*nDim] = [1 x nNs*nDim] - - //**************************************************************************// - // dRblw_vt // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - std::deque<Eigen::Triplet<double>> T_blw; - int offSetElms = 0; - int offSetNodes = 0; - for (const auto& sec: vsol->sections[0]) - { - std::vector<std::vector<double>> grad = sec->evalGradwrtVt(); - for (size_t i = 0; i < grad.size(); ++i) - for (size_t j = 0; j < grad[i].size(); ++j) - T_blw.push_back(Eigen::Triplet<double>(i + offSetElms, j + offSetNodes, -grad[i][j])); - offSetElms += sec->nElms; - offSetNodes += sec->nNodes; + } + dVt_v.setFromTriplets(T_vt.begin(), T_vt.end()); + dVt_v.prune(0.); + + //**************************************************************************// + // dRdStar_vt // + //--------------------------------------------------------------------------// + // Central finite-difference // + //**************************************************************************// + std::deque<Eigen::Triplet<double>> T; + double delta = 1e-6; + i = 0; + double saveM = 0.; + std::vector<Eigen::VectorXd> dvt(2, Eigen::VectorXd::Zero(dRdStar_M.cols())); + std::vector<double> dCdf(2, 0.); + Eigen::VectorXd dCd_vt = Eigen::VectorXd::Zero(dRM_M.cols()); + for (auto sec : vsol->sections[0]) + for (size_t j = 0; j < sec->nNodes; ++j) { + saveM = sec->vt[j]; + + sec->vt[j] = saveM + delta; + dvt[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; + sec->vt[j] = saveM - delta; + dvt[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; + + sec->vt[j] = saveM; + + for (int k = 0; k < dvt[0].size(); ++k) + T.push_back(Eigen::Triplet<double>( + k, i, -(dvt[0][k] - dvt[1][k]) / (2. * delta))); + dCd_vt(i) = (dCdf[0] - dCdf[1]) / (2. * delta); + ++i; } - - Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_vt(nEs, nNs); - dRblw_vt.setFromTriplets(T_blw.begin(), T_blw.end()); - dRblw_vt.prune(0.); - - //**************************************************************************// - // dRblw_v // - //**************************************************************************// - dRblw_v = dRblw_vt * dVt_v; - dRblw_v.prune(0.); + Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_vt(dRdStar_M.rows(), + dRdStar_M.cols()); + dRdStar_vt.setFromTriplets(T.begin(), T.end()); + dRdStar_vt.prune(0.); + + //**************************************************************************// + // dRdStar_v // + //**************************************************************************// + dRdStar_v = dRdStar_vt * dVt_v; + dRdStar_v.prune(0.); + + //**************************************************************************// + // dCdf_v // + //**************************************************************************// + dCd_v = + dCd_vt.transpose() * dVt_v; // [1xnNs] x [nNs x nNs*nDim] = [1 x nNs*nDim] + + //**************************************************************************// + // dRblw_vt // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + std::deque<Eigen::Triplet<double>> T_blw; + int offSetElms = 0; + int offSetNodes = 0; + for (const auto &sec : vsol->sections[0]) { + std::vector<std::vector<double>> grad = sec->evalGradwrtVt(); + for (size_t i = 0; i < grad.size(); ++i) + for (size_t j = 0; j < grad[i].size(); ++j) + T_blw.push_back(Eigen::Triplet<double>(i + offSetElms, j + offSetNodes, + -grad[i][j])); + offSetElms += sec->nElms; + offSetNodes += sec->nNodes; + } + + Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_vt(nEs, nNs); + dRblw_vt.setFromTriplets(T_blw.begin(), T_blw.end()); + dRblw_vt.prune(0.); + + //**************************************************************************// + // dRblw_v // + //**************************************************************************// + dRblw_v = dRblw_vt * dVt_v; + dRblw_v.prune(0.); } /** - * @brief Compute all the gradients wrt the displacement thickness on the surface - * Non-zero are: dRdStar_dStar, dRblw_dStar - * Zeros are: dRphi_dStar, dRM_dStar, dRrho_dStar, dRv_dStar, dRx_dStar + * @brief Compute all the gradients wrt the displacement thickness on the + * surface Non-zero are: dRdStar_dStar, dRblw_dStar Zeros are: dRphi_dStar, + * dRM_dStar, dRrho_dStar, dRv_dStar, dRx_dStar */ -void CoupledAdjoint::gradientswrtDeltaStar() -{ - //**************************************************************************// - // dRdStar_dStar // - //--------------------------------------------------------------------------// - // Central finite-difference // - //**************************************************************************// - std::deque<Eigen::Triplet<double>> T; - double delta = 1e-6; - double saveDStar = 0.; - std::vector<Eigen::VectorXd> ddstar(2, Eigen::VectorXd::Zero(dRdStar_dStar.cols())); - std::vector<double> dCdf(2, 0.); - size_t i = 0; - for (auto sec: vsol->sections[0]) - for (size_t j = 0; j < sec->nNodes; ++j) - { - saveDStar = sec->deltaStarExt[j]; - - sec->deltaStarExt[j] = saveDStar + delta; - ddstar[0] = this->runViscous(); - dCdf[0] = vsol->Cdf; - sec->deltaStarExt[j] = saveDStar - delta; - ddstar[1] = this->runViscous(); - dCdf[1] = vsol->Cdf; - - sec->deltaStarExt[j] = saveDStar; - - for (int k = 0; k < ddstar[0].size(); ++k) - T.push_back(Eigen::Triplet<double>(k, i, (ddstar[0][k] - ddstar[1][k])/(2.*delta))); - dCd_dStar(i) = (dCdf[0] - dCdf[1])/(2.*delta); - ++i; - } - Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_dStar_dum(dRdStar_dStar.rows(), dRdStar_dStar.cols()); - // RdStar = dStar - f(dStar) = 0 - // dRdStar_dStar = 1 - df_dStar (minus is 3 lines below and not in the triplets) - dRdStar_dStar_dum.setFromTriplets(T.begin(), T.end()); - dRdStar_dStar.setIdentity(); - dRdStar_dStar -= dRdStar_dStar_dum; - dRdStar_dStar.prune(0.); - - //**************************************************************************// - // dRblw_dStar // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - std::deque<Eigen::Triplet<double>> T_blw; - int offSetElms = 0; - int offSetNodes = 0; - for (const auto& sec: vsol->sections[0]) - { - std::vector<std::vector<double>> grad = sec->evalGradwrtDeltaStar(); - for (size_t i = 0; i < grad.size(); ++i) - for (size_t j = 0; j < grad[i].size(); ++j) - T_blw.push_back(Eigen::Triplet<double>(i + offSetElms, j + offSetNodes, -grad[i][j])); - offSetElms += sec->nElms; - offSetNodes += sec->nNodes; +void CoupledAdjoint::gradientswrtDeltaStar() { + //**************************************************************************// + // dRdStar_dStar // + //--------------------------------------------------------------------------// + // Central finite-difference // + //**************************************************************************// + std::deque<Eigen::Triplet<double>> T; + double delta = 1e-6; + double saveDStar = 0.; + std::vector<Eigen::VectorXd> ddstar( + 2, Eigen::VectorXd::Zero(dRdStar_dStar.cols())); + std::vector<double> dCdf(2, 0.); + size_t i = 0; + for (auto sec : vsol->sections[0]) + for (size_t j = 0; j < sec->nNodes; ++j) { + saveDStar = sec->deltaStarExt[j]; + + sec->deltaStarExt[j] = saveDStar + delta; + ddstar[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; + sec->deltaStarExt[j] = saveDStar - delta; + ddstar[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; + + sec->deltaStarExt[j] = saveDStar; + + for (int k = 0; k < ddstar[0].size(); ++k) + T.push_back(Eigen::Triplet<double>( + k, i, (ddstar[0][k] - ddstar[1][k]) / (2. * delta))); + dCd_dStar(i) = (dCdf[0] - dCdf[1]) / (2. * delta); + ++i; } - dRblw_dStar.setFromTriplets(T_blw.begin(), T_blw.end()); - dRblw_dStar.prune(0.); + Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_dStar_dum( + dRdStar_dStar.rows(), dRdStar_dStar.cols()); + // RdStar = dStar - f(dStar) = 0 + // dRdStar_dStar = 1 - df_dStar (minus is 3 lines below and not in the + // triplets) + dRdStar_dStar_dum.setFromTriplets(T.begin(), T.end()); + dRdStar_dStar.setIdentity(); + dRdStar_dStar -= dRdStar_dStar_dum; + dRdStar_dStar.prune(0.); + + //**************************************************************************// + // dRblw_dStar // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + std::deque<Eigen::Triplet<double>> T_blw; + int offSetElms = 0; + int offSetNodes = 0; + for (const auto &sec : vsol->sections[0]) { + std::vector<std::vector<double>> grad = sec->evalGradwrtDeltaStar(); + for (size_t i = 0; i < grad.size(); ++i) + for (size_t j = 0; j < grad[i].size(); ++j) + T_blw.push_back(Eigen::Triplet<double>(i + offSetElms, j + offSetNodes, + -grad[i][j])); + offSetElms += sec->nElms; + offSetNodes += sec->nNodes; + } + dRblw_dStar.setFromTriplets(T_blw.begin(), T_blw.end()); + dRblw_dStar.prune(0.); } /** @@ -755,41 +828,40 @@ void CoupledAdjoint::gradientswrtDeltaStar() * Non-zero are: dRphi_blw, dRblw_blw * Zeros are: dRM_blw, dRrho_blw, dRv_blw, dRdStar_blw, dRx_blw */ -void CoupledAdjoint::gradientswrtBlowingVelocity() -{ - //**************************************************************************// - // dRphi_blw // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - std::deque<Eigen::Triplet<double>> T; - - size_t jj = 0; - int iReg = 0; - for (auto sec: vsol->sections[0]){ - if (sec->name == "wake") - iReg = 1; - else if (sec->name == "upper" || sec->name == "lower") - iReg = 0; - else - throw std::runtime_error("Unknown section name"); - for (size_t iElm = 0; iElm < sec->nElms; ++iElm){ - auto blowingElement = isol->pbl->bBCs[iReg]->uE[sec->no[iElm]].first; - Eigen::VectorXd be = dart::BlowingResidual::buildGradientBlowing(*blowingElement); - for (size_t ii = 0; ii < blowingElement->nodes.size(); ii++) - { - tbox::Node *nodi = blowingElement->nodes[ii]; - T.push_back(Eigen::Triplet<double>(isol->rows[nodi->row], jj, be(ii))); - } - ++jj; - } +void CoupledAdjoint::gradientswrtBlowingVelocity() { + //**************************************************************************// + // dRphi_blw // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + std::deque<Eigen::Triplet<double>> T; + + size_t jj = 0; + int iReg = 0; + for (auto sec : vsol->sections[0]) { + if (sec->name == "wake") + iReg = 1; + else if (sec->name == "upper" || sec->name == "lower") + iReg = 0; + else + throw std::runtime_error("Unknown section name"); + for (size_t iElm = 0; iElm < sec->nElms; ++iElm) { + auto blowingElement = isol->pbl->bBCs[iReg]->uE[sec->no[iElm]].first; + Eigen::VectorXd be = + dart::BlowingResidual::buildGradientBlowing(*blowingElement); + for (size_t ii = 0; ii < blowingElement->nodes.size(); ii++) { + tbox::Node *nodi = blowingElement->nodes[ii]; + T.push_back(Eigen::Triplet<double>(isol->rows[nodi->row], jj, be(ii))); + } + ++jj; } - dRphi_blw.setFromTriplets(T.begin(), T.end()); - dRphi_blw.prune(0.); - dRphi_blw.makeCompressed(); + } + dRphi_blw.setFromTriplets(T.begin(), T.end()); + dRphi_blw.prune(0.); + dRphi_blw.makeCompressed(); - /**** dRblw_blw ****/ - dRblw_blw.setIdentity(); + /**** dRblw_blw ****/ + dRblw_blw.setIdentity(); } /** @@ -797,21 +869,22 @@ void CoupledAdjoint::gradientswrtBlowingVelocity() * Non-zero are: dRphi_AoA * Zeros are: dRM_AoA, dRrho_AoA, dRv_AoA, dRdStar_AoA, dRblw_AoA, dRx_AoA */ -void CoupledAdjoint::gradientwrtAoA(){ - //**************************************************************************// - // dCl_Aoa dCd_Aoa // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - std::vector<double> dCx_AoA = iadjoint->computeGradientCoefficientsAoa(); - dCl_AoA = dCx_AoA[0]; dCd_AoA = dCx_AoA[1]; - - //**************************************************************************// - // dRphi_Aoa // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - dRphi_AoA = iadjoint->getRu_A(); +void CoupledAdjoint::gradientwrtAoA() { + //**************************************************************************// + // dCl_Aoa dCd_Aoa // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + std::vector<double> dCx_AoA = iadjoint->computeGradientCoefficientsAoa(); + dCl_AoA = dCx_AoA[0]; + dCd_AoA = dCx_AoA[1]; + + //**************************************************************************// + // dRphi_Aoa // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + dRphi_AoA = iadjoint->getRu_A(); } /** @@ -819,184 +892,198 @@ void CoupledAdjoint::gradientwrtAoA(){ * Non-zero are: dRphi_x, dRM_x, dRrho_x, dRv_x, dRdStar_x, dRblw_x, dRx_x * Zeros are: - */ -void CoupledAdjoint::gradientwrtMesh(){ - - int nDim = isol->pbl->nDim; - - //**************************************************************************// - // dCl_x, dCd_x // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - std::vector<std::vector<double>> dCx_x = iadjoint->computeGradientCoefficientsMesh(); - dCl_x = Eigen::Map<Eigen::VectorXd>(dCx_x[0].data(), dCx_x[0].size()); - dCdp_x = Eigen::Map<Eigen::VectorXd>(dCx_x[1].data(), dCx_x[1].size()); - - //**************************************************************************// - // dRphi_x // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - dRphi_x = iadjoint->getRu_X(); - //**************************************************************************// - // dRx_x // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - dRx_x = iadjoint->getRx_X(); - - //**************************************************************************// - // dRdStar_x, dCdf_dx // - //--------------------------------------------------------------------------// - // Central finite-difference // - //--------------------------------------------------------------------------// - // We don't do dRdStar_x = dRdStar_loc * dloc_dx because Cdf = f(xi(x), x) // - // and we would have to compute dCdf/dx and dCdf/dloc. Same for deltaStar. // - // It is more computationally expansive to compute // - // ddeltaStar/dx, ddeltaStar/dloc than ddeltaStar_dx, ddeltaStar_dy // - //**************************************************************************// - std::deque<Eigen::Triplet<double>> T_dStar_x; - double delta = 1e-8; - int iReg = 0; - std::vector<Eigen::VectorXd> ddStar(2, Eigen::VectorXd::Zero(dRdStar_M.cols())); - std::vector<double> dCdf(2, 0.); - for (auto sec: vsol->sections[0]) - { - if (sec->name == "wake") - iReg = 1; - else if (sec->name == "upper" || sec->name == "lower") - iReg = 0; - else - throw std::runtime_error("Unknown section name"); - for (size_t j = 0; j < sec->nNodes; ++j) - { - int rowj = isol->pbl->bBCs[iReg]->nodes[sec->rows[j]]->row; - // x - double saveX = sec->x[j]; - - sec->x[j] = saveX + delta; - sec->computeLocalCoordinates(); - sec->xxExt = sec->loc; - ddStar[0] = this->runViscous(); - dCdf[0] = vsol->Cdf; - sec->x[j] = saveX - delta; - sec->computeLocalCoordinates(); - sec->xxExt = sec->loc; - ddStar[1] = this->runViscous(); - dCdf[1] = vsol->Cdf; - - sec->x[j] = saveX; - sec->xxExt = sec->loc; - sec->computeLocalCoordinates(); - - for (int k = 0; k < ddStar[0].size(); ++k) - T_dStar_x.push_back(Eigen::Triplet<double>(k, rowj*isol->pbl->nDim+0, -(ddStar[0][k] - ddStar[1][k])/(2.*delta))); - dCdf_x(rowj*isol->pbl->nDim+0) += (dCdf[0] - dCdf[1])/(2.*delta); - // y - double saveY = sec->y[j]; - - sec->y[j] = saveY + delta; - sec->computeLocalCoordinates(); - sec->xxExt = sec->loc; - ddStar[0] = this->runViscous(); - dCdf[0] = vsol->Cdf; - sec->y[j] = saveY - delta; - sec->computeLocalCoordinates(); - sec->xxExt = sec->loc; - ddStar[1] = this->runViscous(); - dCdf[1] = vsol->Cdf; - - sec->y[j] = saveY; - sec->xxExt = sec->loc; - sec->computeLocalCoordinates(); - - for (int k = 0; k < ddStar[0].size(); ++k) - T_dStar_x.push_back(Eigen::Triplet<double>(k, rowj*isol->pbl->nDim+1, -(ddStar[0][k] - ddStar[1][k])/(2.*delta))); - dCdf_x(rowj*isol->pbl->nDim+1) += (dCdf[0] - dCdf[1])/(2.*delta); - } - } - dRdStar_x.setFromTriplets(T_dStar_x.begin(), T_dStar_x.end()); - dRdStar_x.prune(0.); - - //**************************************************************************// - // dRblw_x // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - std::deque<Eigen::Triplet<double>> T_blw_x; - int offSetElms = 0; - for (const auto& sec: vsol->sections[0]) - { - if (sec->name == "wake") - iReg = 1; - else if (sec->name == "upper" || sec->name == "lower") - iReg = 0; - else - throw std::runtime_error("Unknown section name"); - std::vector<std::vector<double>> gradX = sec->evalGradwrtX(); - std::vector<std::vector<double>> gradY = sec->evalGradwrtY(); - for (size_t i = 0; i < gradX.size(); ++i) - for (size_t j = 0; j < gradX[i].size(); ++j) - { - int rowj = isol->pbl->bBCs[iReg]->nodes[sec->rows[j]]->row; - T_blw_x.push_back(Eigen::Triplet<double>(i + offSetElms, rowj*isol->pbl->nDim+0, -gradX[i][j])); - T_blw_x.push_back(Eigen::Triplet<double>(i + offSetElms, rowj*isol->pbl->nDim+1, -gradY[i][j])); - } - offSetElms += sec->nElms; +void CoupledAdjoint::gradientwrtMesh() { + + int nDim = isol->pbl->nDim; + + //**************************************************************************// + // dCl_x, dCd_x // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + std::vector<std::vector<double>> dCx_x = + iadjoint->computeGradientCoefficientsMesh(); + dCl_x = Eigen::Map<Eigen::VectorXd>(dCx_x[0].data(), dCx_x[0].size()); + dCdp_x = Eigen::Map<Eigen::VectorXd>(dCx_x[1].data(), dCx_x[1].size()); + + //**************************************************************************// + // dRphi_x // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + dRphi_x = iadjoint->getRu_X(); + //**************************************************************************// + // dRx_x // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + dRx_x = iadjoint->getRx_X(); + + //**************************************************************************// + // dRdStar_x, dCdf_dx // + //--------------------------------------------------------------------------// + // Central finite-difference // + //--------------------------------------------------------------------------// + // We don't do dRdStar_x = dRdStar_loc * dloc_dx because Cdf = f(xi(x), x) // + // and we would have to compute dCdf/dx and dCdf/dloc. Same for deltaStar. // + // It is more computationally expansive to compute // + // ddeltaStar/dx, ddeltaStar/dloc than ddeltaStar_dx, ddeltaStar_dy // + //**************************************************************************// + std::deque<Eigen::Triplet<double>> T_dStar_x; + double delta = 1e-8; + int iReg = 0; + std::vector<Eigen::VectorXd> ddStar(2, + Eigen::VectorXd::Zero(dRdStar_M.cols())); + std::vector<double> dCdf(2, 0.); + for (auto sec : vsol->sections[0]) { + if (sec->name == "wake") + iReg = 1; + else if (sec->name == "upper" || sec->name == "lower") + iReg = 0; + else + throw std::runtime_error("Unknown section name"); + for (size_t j = 0; j < sec->nNodes; ++j) { + int rowj = isol->pbl->bBCs[iReg]->nodes[sec->rows[j]]->row; + // x + double saveX = sec->x[j]; + + sec->x[j] = saveX + delta; + sec->computeLocalCoordinates(); + sec->xxExt = sec->loc; + ddStar[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; + sec->x[j] = saveX - delta; + sec->computeLocalCoordinates(); + sec->xxExt = sec->loc; + ddStar[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; + + sec->x[j] = saveX; + sec->xxExt = sec->loc; + sec->computeLocalCoordinates(); + + for (int k = 0; k < ddStar[0].size(); ++k) + T_dStar_x.push_back(Eigen::Triplet<double>( + k, rowj * isol->pbl->nDim + 0, + -(ddStar[0][k] - ddStar[1][k]) / (2. * delta))); + dCdf_x(rowj * isol->pbl->nDim + 0) += (dCdf[0] - dCdf[1]) / (2. * delta); + // y + double saveY = sec->y[j]; + + sec->y[j] = saveY + delta; + sec->computeLocalCoordinates(); + sec->xxExt = sec->loc; + ddStar[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; + sec->y[j] = saveY - delta; + sec->computeLocalCoordinates(); + sec->xxExt = sec->loc; + ddStar[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; + + sec->y[j] = saveY; + sec->xxExt = sec->loc; + sec->computeLocalCoordinates(); + + for (int k = 0; k < ddStar[0].size(); ++k) + T_dStar_x.push_back(Eigen::Triplet<double>( + k, rowj * isol->pbl->nDim + 1, + -(ddStar[0][k] - ddStar[1][k]) / (2. * delta))); + dCdf_x(rowj * isol->pbl->nDim + 1) += (dCdf[0] - dCdf[1]) / (2. * delta); } - dRblw_x.setFromTriplets(T_blw_x.begin(), T_blw_x.end()); - dRblw_x.prune(0.); - - //**************************************************************************// - // dRM_x, dRrho_x, dRv_x // - //--------------------------------------------------------------------------// - // Analytical // - //**************************************************************************// - auto pbl = isol->pbl; - - std::deque<Eigen::Triplet<double>> T_dM_x; - std::deque<Eigen::Triplet<double>> T_drho_x; - std::deque<Eigen::Triplet<double>> T_dv_x; - - int jj = 0; - iReg = 0; - - for (auto sec : vsol->sections[0]) - { - if (sec->name == "wake") - iReg = 1; - else if (sec->name == "upper" || sec->name == "lower") - iReg = 0; - else - throw std::runtime_error("gradientswrtInviscidFlow: Unknown section name"); - for (size_t iNode = 0; iNode < sec->nNodes; ++iNode) - { - tbox::Node* srfNode = pbl->bBCs[iReg]->nodes[sec->rows[iNode]]; - double nAdjElms = static_cast<double>(pbl->fluid->neMap[srfNode].size()); - for (auto e: pbl->fluid->neMap[srfNode]) - { - // dv/dx = dv/dgradPhi * dgradPhi/dx = dgradPhi/dx = (-J^(-1) * dJ/dx_j)*grad_xPhi - // dM/dx = dM/dgradPhi * dgradPhi/dx = dM/dgradPhi * gradPhi * dv/dx - // drho/dx = drho/dgradPhi * dgradPhi/dx = drho/dgradPhi * gradPhi * dv/dx - for (int inodOnElm = 0; inodOnElm < e->nodes.size(); inodOnElm++) - for (int idim = 0; idim < nDim; ++idim) - { - Eigen::VectorXd gradV = (-e->getJinv(0)) * e->getGradJ(0)[inodOnElm*nDim + idim] * e->computeGradient(isol->phi, 0); - double gradM = pbl->fluid->mach->evalGrad(*e, isol->phi, 0) * e->computeGradient(isol->phi, 0).transpose() * gradV; - double gradrho = pbl->fluid->rho->evalGrad(*e, isol->phi, 0) * e->computeGradient(isol->phi, 0).transpose() * gradV; - T_dM_x.push_back(Eigen::Triplet<double>(jj, e->nodes[inodOnElm]->row*nDim + idim, -gradM/nAdjElms)); - T_drho_x.push_back(Eigen::Triplet<double>(jj, e->nodes[inodOnElm]->row*nDim + idim, -gradrho/nAdjElms)); - for (int idim2 = 0; idim2 < nDim; idim2++) - T_dv_x.push_back(Eigen::Triplet<double>(jj*nDim + idim2, e->nodes[inodOnElm]->row*nDim + idim, -gradV(idim2)/nAdjElms)); - } - } - ++jj; - } + } + dRdStar_x.setFromTriplets(T_dStar_x.begin(), T_dStar_x.end()); + dRdStar_x.prune(0.); + + //**************************************************************************// + // dRblw_x // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + std::deque<Eigen::Triplet<double>> T_blw_x; + int offSetElms = 0; + for (const auto &sec : vsol->sections[0]) { + if (sec->name == "wake") + iReg = 1; + else if (sec->name == "upper" || sec->name == "lower") + iReg = 0; + else + throw std::runtime_error("Unknown section name"); + std::vector<std::vector<double>> gradX = sec->evalGradwrtX(); + std::vector<std::vector<double>> gradY = sec->evalGradwrtY(); + for (size_t i = 0; i < gradX.size(); ++i) + for (size_t j = 0; j < gradX[i].size(); ++j) { + int rowj = isol->pbl->bBCs[iReg]->nodes[sec->rows[j]]->row; + T_blw_x.push_back(Eigen::Triplet<double>( + i + offSetElms, rowj * isol->pbl->nDim + 0, -gradX[i][j])); + T_blw_x.push_back(Eigen::Triplet<double>( + i + offSetElms, rowj * isol->pbl->nDim + 1, -gradY[i][j])); + } + offSetElms += sec->nElms; + } + dRblw_x.setFromTriplets(T_blw_x.begin(), T_blw_x.end()); + dRblw_x.prune(0.); + + //**************************************************************************// + // dRM_x, dRrho_x, dRv_x // + //--------------------------------------------------------------------------// + // Analytical // + //**************************************************************************// + auto pbl = isol->pbl; + + std::deque<Eigen::Triplet<double>> T_dM_x; + std::deque<Eigen::Triplet<double>> T_drho_x; + std::deque<Eigen::Triplet<double>> T_dv_x; + + int jj = 0; + iReg = 0; + + for (auto sec : vsol->sections[0]) { + if (sec->name == "wake") + iReg = 1; + else if (sec->name == "upper" || sec->name == "lower") + iReg = 0; + else + throw std::runtime_error( + "gradientswrtInviscidFlow: Unknown section name"); + for (size_t iNode = 0; iNode < sec->nNodes; ++iNode) { + tbox::Node *srfNode = pbl->bBCs[iReg]->nodes[sec->rows[iNode]]; + double nAdjElms = static_cast<double>(pbl->fluid->neMap[srfNode].size()); + for (auto e : pbl->fluid->neMap[srfNode]) { + // dv/dx = dv/dgradPhi * dgradPhi/dx = dgradPhi/dx = (-J^(-1) * + // dJ/dx_j)*grad_xPhi dM/dx = dM/dgradPhi * dgradPhi/dx = dM/dgradPhi * + // gradPhi * dv/dx drho/dx = drho/dgradPhi * dgradPhi/dx = drho/dgradPhi + // * gradPhi * dv/dx + for (int inodOnElm = 0; inodOnElm < e->nodes.size(); inodOnElm++) + for (int idim = 0; idim < nDim; ++idim) { + Eigen::VectorXd gradV = (-e->getJinv(0)) * + e->getGradJ(0)[inodOnElm * nDim + idim] * + e->computeGradient(isol->phi, 0); + double gradM = pbl->fluid->mach->evalGrad(*e, isol->phi, 0) * + e->computeGradient(isol->phi, 0).transpose() * gradV; + double gradrho = pbl->fluid->rho->evalGrad(*e, isol->phi, 0) * + e->computeGradient(isol->phi, 0).transpose() * + gradV; + T_dM_x.push_back(Eigen::Triplet<double>( + jj, e->nodes[inodOnElm]->row * nDim + idim, -gradM / nAdjElms)); + T_drho_x.push_back(Eigen::Triplet<double>( + jj, e->nodes[inodOnElm]->row * nDim + idim, + -gradrho / nAdjElms)); + for (int idim2 = 0; idim2 < nDim; idim2++) + T_dv_x.push_back(Eigen::Triplet<double>( + jj * nDim + idim2, e->nodes[inodOnElm]->row * nDim + idim, + -gradV(idim2) / nAdjElms)); + } + } + ++jj; } - dRM_x.setFromTriplets(T_dM_x.begin(), T_dM_x.end()); - dRrho_x.setFromTriplets(T_drho_x.begin(), T_drho_x.end()); - dRv_x.setFromTriplets(T_dv_x.begin(), T_dv_x.end()); - dRM_x.prune(0.); dRrho_x.prune(0.); dRv_x.prune(0.); + } + dRM_x.setFromTriplets(T_dM_x.begin(), T_dM_x.end()); + dRrho_x.setFromTriplets(T_drho_x.begin(), T_drho_x.end()); + dRv_x.setFromTriplets(T_dv_x.begin(), T_dv_x.end()); + dRM_x.prune(0.); + dRrho_x.prune(0.); + dRv_x.prune(0.); } /** @@ -1005,83 +1092,84 @@ void CoupledAdjoint::gradientwrtMesh(){ * * @return Eigen::VectorXd deltaStar */ -Eigen::VectorXd CoupledAdjoint::runViscous() -{ - int exitCode = vsol->run(); - // if (exitCode != 0) - // std::cout << "vsol terminated with exit code " << exitCode << std::endl; - - // Extract deltaStar - std::vector<Eigen::VectorXd> dStar_p; - - // Extract parts in a loop - for (size_t i = 0; i < vsol->sections[0].size(); ++i) { - std::vector<double> deltaStar_vec = this->vsol->sections[0][i]->deltaStar; - Eigen::VectorXd deltaStar_eigen = Eigen::Map<Eigen::VectorXd>(deltaStar_vec.data(), deltaStar_vec.size()); - dStar_p.push_back(deltaStar_eigen); - } - // Calculate the total size - int nNs = 0; - for (const auto& p : dStar_p) - nNs += p.size(); - - // Concatenate the vectors - Eigen::VectorXd deltaStar(nNs); - int idx = 0; - for (const auto& p : dStar_p) { - deltaStar.segment(idx, p.size()) = p; - idx += p.size(); - } - return deltaStar; +Eigen::VectorXd CoupledAdjoint::runViscous() { + int exitCode = vsol->run(); + // if (exitCode != 0) + // std::cout << "vsol terminated with exit code " << exitCode << + // std::endl; + + // Extract deltaStar + std::vector<Eigen::VectorXd> dStar_p; + + // Extract parts in a loop + for (size_t i = 0; i < vsol->sections[0].size(); ++i) { + std::vector<double> deltaStar_vec = this->vsol->sections[0][i]->deltaStar; + Eigen::VectorXd deltaStar_eigen = + Eigen::Map<Eigen::VectorXd>(deltaStar_vec.data(), deltaStar_vec.size()); + dStar_p.push_back(deltaStar_eigen); + } + // Calculate the total size + int nNs = 0; + for (const auto &p : dStar_p) + nNs += p.size(); + + // Concatenate the vectors + Eigen::VectorXd deltaStar(nNs); + int idx = 0; + for (const auto &p : dStar_p) { + deltaStar.segment(idx, p.size()) = p; + idx += p.size(); + } + return deltaStar; } /** - * @brief Transpose all matrices of the adjoint problem included in the system. Not the others. + * @brief Transpose all matrices of the adjoint problem included in the system. + * Not the others. */ -void CoupledAdjoint::transposeMatrices(){ - - dRphi_phi = dRphi_phi.transpose(); - dRphi_M = dRphi_M.transpose(); - dRphi_rho = dRphi_rho.transpose(); - dRphi_v = dRphi_v.transpose(); - dRphi_dStar = dRphi_dStar.transpose(); - dRphi_blw = dRphi_blw.transpose(); - - dRM_phi = dRM_phi.transpose(); - dRM_M = dRM_M.transpose(); - dRM_rho = dRM_rho.transpose(); - dRM_v = dRM_v.transpose(); - dRM_dStar = dRM_dStar.transpose(); - dRM_blw = dRM_blw.transpose(); - - dRrho_phi = dRrho_phi.transpose(); - dRrho_M = dRrho_M.transpose(); - dRrho_rho = dRrho_rho.transpose(); - dRrho_v = dRrho_v.transpose(); - dRrho_dStar = dRrho_dStar.transpose(); - dRrho_blw = dRrho_blw.transpose(); - - dRv_phi = dRv_phi.transpose(); - dRv_M = dRv_M.transpose(); - dRv_rho = dRv_rho.transpose(); - dRv_v = dRv_v.transpose(); - dRv_dStar = dRv_dStar.transpose(); - dRv_blw = dRv_blw.transpose(); - - dRdStar_phi = dRdStar_phi.transpose(); - dRdStar_M = dRdStar_M.transpose(); - dRdStar_rho = dRdStar_rho.transpose(); - dRdStar_v = dRdStar_v.transpose(); - dRdStar_dStar = dRdStar_dStar.transpose(); - dRdStar_blw = dRdStar_blw.transpose(); - - dRblw_phi = dRblw_phi.transpose(); - dRblw_M = dRblw_M.transpose(); - dRblw_rho = dRblw_rho.transpose(); - dRblw_v = dRblw_v.transpose(); - dRblw_dStar = dRblw_dStar.transpose(); - dRblw_blw = dRblw_blw.transpose(); - +void CoupledAdjoint::transposeMatrices() { + + dRphi_phi = dRphi_phi.transpose(); + dRphi_M = dRphi_M.transpose(); + dRphi_rho = dRphi_rho.transpose(); + dRphi_v = dRphi_v.transpose(); + dRphi_dStar = dRphi_dStar.transpose(); + dRphi_blw = dRphi_blw.transpose(); + + dRM_phi = dRM_phi.transpose(); + dRM_M = dRM_M.transpose(); + dRM_rho = dRM_rho.transpose(); + dRM_v = dRM_v.transpose(); + dRM_dStar = dRM_dStar.transpose(); + dRM_blw = dRM_blw.transpose(); + + dRrho_phi = dRrho_phi.transpose(); + dRrho_M = dRrho_M.transpose(); + dRrho_rho = dRrho_rho.transpose(); + dRrho_v = dRrho_v.transpose(); + dRrho_dStar = dRrho_dStar.transpose(); + dRrho_blw = dRrho_blw.transpose(); + + dRv_phi = dRv_phi.transpose(); + dRv_M = dRv_M.transpose(); + dRv_rho = dRv_rho.transpose(); + dRv_v = dRv_v.transpose(); + dRv_dStar = dRv_dStar.transpose(); + dRv_blw = dRv_blw.transpose(); + + dRdStar_phi = dRdStar_phi.transpose(); + dRdStar_M = dRdStar_M.transpose(); + dRdStar_rho = dRdStar_rho.transpose(); + dRdStar_v = dRdStar_v.transpose(); + dRdStar_dStar = dRdStar_dStar.transpose(); + dRdStar_blw = dRdStar_blw.transpose(); + + dRblw_phi = dRblw_phi.transpose(); + dRblw_M = dRblw_M.transpose(); + dRblw_rho = dRblw_rho.transpose(); + dRblw_v = dRblw_v.transpose(); + dRblw_dStar = dRblw_dStar.transpose(); + dRblw_blw = dRblw_blw.transpose(); } /** @@ -1089,34 +1177,36 @@ void CoupledAdjoint::transposeMatrices(){ * @param matrix Eigen matrix to write * @param filename Name of the file to write * @return void - * + * * The matrices are written in a file with the following format: * - The first line contains the column headers * - The following lines contain the matrix data * - The matrix data is written with a precision of 12 digits */ -void CoupledAdjoint::writeMatrixToFile(const Eigen::MatrixXd& matrix, const std::string& filename) { - std::ofstream file(filename); - if (file.is_open()) { - // Write the column headers - for (int j = 0; j < matrix.cols(); ++j) { - file << std::setw(15) << j; - if (j != matrix.cols() - 1) { - file << " "; - } - } - file << "\n"; - - // Write the matrix data - for (int i = 0; i < matrix.rows(); ++i) { - for (int j = 0; j < matrix.cols(); ++j) { - file << std::fixed << std::setprecision(12) << std::setw(15) << matrix(i, j); - if (j != matrix.cols() - 1) { - file << " "; - } - } - file << "\n"; +void CoupledAdjoint::writeMatrixToFile(const Eigen::MatrixXd &matrix, + const std::string &filename) { + std::ofstream file(filename); + if (file.is_open()) { + // Write the column headers + for (int j = 0; j < matrix.cols(); ++j) { + file << std::setw(15) << j; + if (j != matrix.cols() - 1) { + file << " "; + } + } + file << "\n"; + + // Write the matrix data + for (int i = 0; i < matrix.rows(); ++i) { + for (int j = 0; j < matrix.cols(); ++j) { + file << std::fixed << std::setprecision(12) << std::setw(15) + << matrix(i, j); + if (j != matrix.cols() - 1) { + file << " "; } - file.close(); + } + file << "\n"; } + file.close(); + } } diff --git a/blast/src/DCoupledAdjoint.h b/blast/src/DCoupledAdjoint.h index 2cfa4ab..f9a006d 100644 --- a/blast/src/DCoupledAdjoint.h +++ b/blast/src/DCoupledAdjoint.h @@ -18,131 +18,234 @@ #define DCOUPLEDADJOINT_H #include "blast.h" -#include "wObject.h" #include "dart.h" +#include "wObject.h" #include "wTimers.h" #include <Eigen/Sparse> #include <iostream> #include <memory> -namespace blast -{ +namespace blast { /** * @brief Adjoint of the coupled system. * @author Paul Dechamps */ -class BLAST_API CoupledAdjoint : public fwk::wSharedObject -{ +class BLAST_API CoupledAdjoint : public fwk::wSharedObject { public: - std::shared_ptr<dart::Adjoint> iadjoint; ///< Adjoint solver - std::shared_ptr<dart::Newton> isol; ///< Inviscid Newton solver - std::shared_ptr<blast::Driver> vsol; ///< Viscous solver - std::shared_ptr<tbox::LinearSolver> alinsol; ///< linear solver (adjoint aero) - - double tdCl_AoA; ///< Total derivative of the lift coefficient with respect to the angle of attack - double tdCd_AoA; ///< Total erivative of the drag coefficient with respect to the angle of attack - - std::vector<Eigen::Vector3d> tdCl_x; ///< Total derivative of the lift coefficient with respect to the mesh coordinates - std::vector<Eigen::Vector3d> tdCd_x; ///< Total derivative of the drag coefficient with respect to the mesh coordinates + std::shared_ptr<dart::Adjoint> iadjoint; ///< Adjoint solver + std::shared_ptr<dart::Newton> isol; ///< Inviscid Newton solver + std::shared_ptr<blast::Driver> vsol; ///< Viscous solver + std::shared_ptr<tbox::LinearSolver> alinsol; ///< linear solver (adjoint aero) + + double tdCl_AoA; ///< Total derivative of the lift coefficient with respect to + ///< the angle of attack + double tdCd_AoA; ///< Total erivative of the drag coefficient with respect to + ///< the angle of attack + + std::vector<Eigen::Vector3d> + tdCl_x; ///< Total derivative of the lift coefficient with respect to the + ///< mesh coordinates + std::vector<Eigen::Vector3d> + tdCd_x; ///< Total derivative of the drag coefficient with respect to the + ///< mesh coordinates private: - Eigen::SparseMatrix<double, Eigen::RowMajor> dRphi_phi; ///< Inviscid flow Jacobian - Eigen::SparseMatrix<double, Eigen::RowMajor> dRphi_M; ///< Derivative of the inviscid flow residual with respect to the Mach number - Eigen::SparseMatrix<double, Eigen::RowMajor> dRphi_v; ///< Derivative of the inviscid flow residual with respect to the velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRphi_rho; ///< Derivative of the inviscid flow residual with respect to the density - Eigen::SparseMatrix<double, Eigen::RowMajor> dRphi_dStar; ///< Derivative of the inviscid flow residual with respect to delta* - Eigen::SparseMatrix<double, Eigen::RowMajor> dRphi_blw; ///< Derivative of the inviscid flow residual with respect to the blowing velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRphi_x; ///< Derivative of the potential residual with respect to the mesh coordinates - - Eigen::SparseMatrix<double, Eigen::RowMajor> dRM_phi; ///< Derivative of the Mach number residual with respect to the inviscid flow - Eigen::SparseMatrix<double, Eigen::RowMajor> dRM_M; ///< Derivative of the Mach number residual with respect to the Mach number - Eigen::SparseMatrix<double, Eigen::RowMajor> dRM_v; ///< Derivative of the Mach number residual with respect to the velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRM_rho; ///< Derivative of the Mach number residual with respect to the density - Eigen::SparseMatrix<double, Eigen::RowMajor> dRM_dStar; ///< Derivative of the Mach number residual with respect to delta* - Eigen::SparseMatrix<double, Eigen::RowMajor> dRM_blw; ///< Derivative of the Mach number residual with respect to the blowing velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRM_x; ///< Derivative of the Mach number residual with respect to the mesh coordinates - - Eigen::SparseMatrix<double, Eigen::RowMajor> dRrho_phi; ///< Derivative of the density residual with respect to the inviscid flow - Eigen::SparseMatrix<double, Eigen::RowMajor> dRrho_M; ///< Derivative of the density residual with respect to the Mach number - Eigen::SparseMatrix<double, Eigen::RowMajor> dRrho_v; ///< Derivative of the density residual with respect to the velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRrho_rho; ///< Derivative of the density residual with respect to the density - Eigen::SparseMatrix<double, Eigen::RowMajor> dRrho_dStar; ///< Derivative of the density residual with respect to delta* - Eigen::SparseMatrix<double, Eigen::RowMajor> dRrho_blw; ///< Derivative of the density residual with respect to the blowing velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRrho_x; ///< Derivative of the density residual with respect to the mesh coordinates - - Eigen::SparseMatrix<double, Eigen::RowMajor> dRv_phi; ///< Derivative of the velocity residual with respect to the inviscid flow - Eigen::SparseMatrix<double, Eigen::RowMajor> dRv_M; ///< Derivative of the velocity residual with respect to the Mach number - Eigen::SparseMatrix<double, Eigen::RowMajor> dRv_v; ///< Derivative of the velocity residual with respect to the velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRv_rho; ///< Derivative of the velocity residual with respect to the density - Eigen::SparseMatrix<double, Eigen::RowMajor> dRv_dStar; ///< Derivative of the velocity residual with respect to delta* - Eigen::SparseMatrix<double, Eigen::RowMajor> dRv_blw; ///< Derivative of the velocity residual with respect to the blowing velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRv_x; ///< Derivative of the velocity residual with respect to the mesh coordinates - - Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_phi; ///< Derivative of delta* residual with respect to the inviscid flow - Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_M; ///< Derivative of delta* residual with respect to the Mach number - Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_v; ///< Derivative of delta* residual with respect to the velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_rho; ///< Derivative of delta* residual with respect to the density - Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_dStar; ///< Derivative of delta* residual with respect to delta* - Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_blw; ///< Derivative of delta* residual with respect to the blowing velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_x; ///< Derivative of delta* residual with respect to the mesh coordinates - - Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_phi; ///< Derivative of the blowing velocity residual with respect to the inviscid flow - Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_M; ///< Derivative of the blowing velocity residual with respect to the Mach number - Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_v; ///< Derivative of the blowing velocity residual with respect to the velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_rho; ///< Derivative of the blowing velocity residual with respect to the density - Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_dStar; ///< Derivative of the blowing velocity residual with respect to delta* - Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_blw; ///< Derivative of the blowing velocity residual with respect to the blowing velocity - Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_x; ///< Derivative of the blowing velocity residual with respect to the mesh coordinates - - // Objective functions - Eigen::VectorXd dCl_phi; ///< Derivative of the lift coefficient with respect to the inviscid flow - Eigen::VectorXd dCd_phi; ///< Derivative of the drag coefficient with respect to the inviscid flow - Eigen::VectorXd dCd_M; ///< Derivative of the drag coefficient with respect to the Mach number - Eigen::VectorXd dCd_rho; ///< Derivative of the drag coefficient with respect to the density - Eigen::VectorXd dCd_v; ///< Derivative of the drag coefficient with respect to the velocity - Eigen::VectorXd dCd_dStar; ///< Derivative of the drag coefficient with respect to delta* - - // Angle of attack - Eigen::VectorXd dRphi_AoA; ///< Derivative of the inviscid flow residual with respect to the angle of attack - double dCl_AoA; ///< Partial derivative of the lift coefficient with respect to the angle of attack - double dCd_AoA; ///< Partial derivative of the total drag coefficient with respect to the angle of attack - - // Mesh - Eigen::SparseMatrix<double, Eigen::RowMajor> dRx_x; ///< Derivative of the mesh residual with respect to the mesh coordinates - Eigen::VectorXd dCl_x; ///< Partial derivative of the lift coefficient with respect to the mesh coordinates - Eigen::VectorXd dCdp_x; ///< Partial derivative of the pressure drag coefficient with respect to the mesh coordinates - Eigen::VectorXd dCdf_x; ///< Partial derivative of the friction drag coefficient with respect to the mesh coordinates - - fwk::Timers tms; //< internal timers - fwk::Timers tms2; //< internal precise timers + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRphi_phi; ///< Inviscid flow Jacobian + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRphi_M; ///< Derivative of the inviscid flow residual with respect to the + ///< Mach number + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRphi_v; ///< Derivative of the inviscid flow residual with respect to the + ///< velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRphi_rho; ///< Derivative of the inviscid flow residual with respect to + ///< the density + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRphi_dStar; ///< Derivative of the inviscid flow residual with respect to + ///< delta* + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRphi_blw; ///< Derivative of the inviscid flow residual with respect to + ///< the blowing velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRphi_x; ///< Derivative of the potential residual with respect to the + ///< mesh coordinates + + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRM_phi; ///< Derivative of the Mach number residual with respect to the + ///< inviscid flow + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRM_M; ///< Derivative of the Mach number residual with respect to the + ///< Mach number + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRM_v; ///< Derivative of the Mach number residual with respect to the + ///< velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRM_rho; ///< Derivative of the Mach number residual with respect to the + ///< density + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRM_dStar; ///< Derivative of the Mach number residual with respect to + ///< delta* + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRM_blw; ///< Derivative of the Mach number residual with respect to the + ///< blowing velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRM_x; ///< Derivative of the Mach number residual with respect to the + ///< mesh coordinates + + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRrho_phi; ///< Derivative of the density residual with respect to the + ///< inviscid flow + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRrho_M; ///< Derivative of the density residual with respect to the Mach + ///< number + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRrho_v; ///< Derivative of the density residual with respect to the + ///< velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRrho_rho; ///< Derivative of the density residual with respect to the + ///< density + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRrho_dStar; ///< Derivative of the density residual with respect to + ///< delta* + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRrho_blw; ///< Derivative of the density residual with respect to the + ///< blowing velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRrho_x; ///< Derivative of the density residual with respect to the mesh + ///< coordinates + + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRv_phi; ///< Derivative of the velocity residual with respect to the + ///< inviscid flow + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRv_M; ///< Derivative of the velocity residual with respect to the Mach + ///< number + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRv_v; ///< Derivative of the velocity residual with respect to the + ///< velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRv_rho; ///< Derivative of the velocity residual with respect to the + ///< density + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRv_dStar; ///< Derivative of the velocity residual with respect to delta* + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRv_blw; ///< Derivative of the velocity residual with respect to the + ///< blowing velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRv_x; ///< Derivative of the velocity residual with respect to the mesh + ///< coordinates + + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRdStar_phi; ///< Derivative of delta* residual with respect to the + ///< inviscid flow + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRdStar_M; ///< Derivative of delta* residual with respect to the Mach + ///< number + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRdStar_v; ///< Derivative of delta* residual with respect to the velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRdStar_rho; ///< Derivative of delta* residual with respect to the + ///< density + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRdStar_dStar; ///< Derivative of delta* residual with respect to delta* + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRdStar_blw; ///< Derivative of delta* residual with respect to the + ///< blowing velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRdStar_x; ///< Derivative of delta* residual with respect to the mesh + ///< coordinates + + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRblw_phi; ///< Derivative of the blowing velocity residual with respect + ///< to the inviscid flow + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRblw_M; ///< Derivative of the blowing velocity residual with respect to + ///< the Mach number + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRblw_v; ///< Derivative of the blowing velocity residual with respect to + ///< the velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRblw_rho; ///< Derivative of the blowing velocity residual with respect + ///< to the density + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRblw_dStar; ///< Derivative of the blowing velocity residual with respect + ///< to delta* + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRblw_blw; ///< Derivative of the blowing velocity residual with respect + ///< to the blowing velocity + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRblw_x; ///< Derivative of the blowing velocity residual with respect to + ///< the mesh coordinates + + // Objective functions + Eigen::VectorXd dCl_phi; ///< Derivative of the lift coefficient with respect + ///< to the inviscid flow + Eigen::VectorXd dCd_phi; ///< Derivative of the drag coefficient with respect + ///< to the inviscid flow + Eigen::VectorXd dCd_M; ///< Derivative of the drag coefficient with respect to + ///< the Mach number + Eigen::VectorXd dCd_rho; ///< Derivative of the drag coefficient with respect + ///< to the density + Eigen::VectorXd dCd_v; ///< Derivative of the drag coefficient with respect to + ///< the velocity + Eigen::VectorXd + dCd_dStar; ///< Derivative of the drag coefficient with respect to delta* + + // Angle of attack + Eigen::VectorXd dRphi_AoA; ///< Derivative of the inviscid flow residual with + ///< respect to the angle of attack + double dCl_AoA; ///< Partial derivative of the lift coefficient with respect + ///< to the angle of attack + double dCd_AoA; ///< Partial derivative of the total drag coefficient with + ///< respect to the angle of attack + + // Mesh + Eigen::SparseMatrix<double, Eigen::RowMajor> + dRx_x; ///< Derivative of the mesh residual with respect to the mesh + ///< coordinates + Eigen::VectorXd dCl_x; ///< Partial derivative of the lift coefficient with + ///< respect to the mesh coordinates + Eigen::VectorXd dCdp_x; ///< Partial derivative of the pressure drag + ///< coefficient with respect to the mesh coordinates + Eigen::VectorXd dCdf_x; ///< Partial derivative of the friction drag + ///< coefficient with respect to the mesh coordinates + + fwk::Timers tms; //< internal timers + fwk::Timers tms2; //< internal precise timers public: - CoupledAdjoint(std::shared_ptr<dart::Adjoint> iAdjoint, std::shared_ptr<blast::Driver> vSolver); - virtual ~CoupledAdjoint () {std::cout << "~blast::CoupledAdjoint()\n";}; + CoupledAdjoint(std::shared_ptr<dart::Adjoint> iAdjoint, + std::shared_ptr<blast::Driver> vSolver); + virtual ~CoupledAdjoint() { std::cout << "~blast::CoupledAdjoint()\n"; }; - void run(); - void reset(); + void run(); + void reset(); private: - void buildAdjointMatrix(std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor>*>> &matrices, Eigen::SparseMatrix<double, Eigen::RowMajor> &matrixAdjoint); - - Eigen::VectorXd runViscous(); - - void gradientswrtInviscidFlow(); - void gradientswrtMachNumber(); - void gradientswrtDensity(); - void gradientswrtVelocity(); - void gradientswrtDeltaStar(); - void gradientswrtBlowingVelocity(); - - void gradientwrtAoA(); - void gradientwrtMesh(); - - void transposeMatrices(); - void writeMatrixToFile(const Eigen::MatrixXd& matrix, const std::string& filename); + void buildAdjointMatrix( + std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor> *>> + &matrices, + Eigen::SparseMatrix<double, Eigen::RowMajor> &matrixAdjoint); + + Eigen::VectorXd runViscous(); + + void gradientswrtInviscidFlow(); + void gradientswrtMachNumber(); + void gradientswrtDensity(); + void gradientswrtVelocity(); + void gradientswrtDeltaStar(); + void gradientswrtBlowingVelocity(); + + void gradientwrtAoA(); + void gradientwrtMesh(); + + void transposeMatrices(); + void writeMatrixToFile(const Eigen::MatrixXd &matrix, + const std::string &filename); }; } // namespace blast #endif // DDARTADJOINT diff --git a/blast/src/DDriver.cpp b/blast/src/DDriver.cpp index 050c6dc..575682b 100644 --- a/blast/src/DDriver.cpp +++ b/blast/src/DDriver.cpp @@ -21,313 +21,333 @@ using namespace blast; * @param _verbose Verbosity level of the solver 0<=verbose<=1. */ Driver::Driver(double _Re, double _Minf, double _CFL0, size_t nSections, - double xtrF_top, double xtrF_bot, double _span, unsigned int _verbose) -{ - // Freestream parameters. - Re = _Re; - CFL0 = _CFL0; - verbose = _verbose; - - std::vector<double> xtrF = {xtrF_top, xtrF_bot, 0.}; - - // Initialzing boundary layer - sections.resize(nSections); - solverExitCode = 0; - convergenceStatus.resize(nSections); - for (size_t iSec = 0; iSec < nSections; ++iSec) - convergenceStatus[iSec].resize(3); - - Cdt_sec.resize(sections.size(), 0.); - Cdf_sec.resize(sections.size(), 0.); - Cdp_sec.resize(sections.size(), 0.); - Cdt = 0.; - Cdf = 0.; - Cdp = 0.; - span = _span; - - // Time solver initialization. - tSolver = new Solver(_CFL0, _Minf, Re); - - // Numerical parameters. - std::cout << "--- Viscous solver setup ---\n" - << "Reynolds number: " << Re << " \n" - << "Freestream Mach number: " << _Minf << " \n" - << "Initial CFL number: " << CFL0 << " \n" - << std::endl; - std::cout << "Boundary layer initialized." << std::endl; + double xtrF_top, double xtrF_bot, double _span, + unsigned int _verbose) { + // Freestream parameters. + Re = _Re; + CFL0 = _CFL0; + verbose = _verbose; + + std::vector<double> xtrF = {xtrF_top, xtrF_bot, 0.}; + + // Initialzing boundary layer + sections.resize(nSections); + solverExitCode = 0; + convergenceStatus.resize(nSections); + for (size_t iSec = 0; iSec < nSections; ++iSec) + convergenceStatus[iSec].resize(3); + + Cdt_sec.resize(sections.size(), 0.); + Cdf_sec.resize(sections.size(), 0.); + Cdp_sec.resize(sections.size(), 0.); + Cdt = 0.; + Cdf = 0.; + Cdp = 0.; + span = _span; + + // Time solver initialization. + tSolver = new Solver(_CFL0, _Minf, Re); + + // Numerical parameters. + std::cout << "--- Viscous solver setup ---\n" + << "Reynolds number: " << Re << " \n" + << "Freestream Mach number: " << _Minf << " \n" + << "Initial CFL number: " << CFL0 << " \n" + << std::endl; + std::cout << "Boundary layer initialized." << std::endl; } /** * @brief Driver and subsequent dependencies destruction. */ -Driver::~Driver() -{ - delete tSolver; - std::cout << "~blast::Driver()\n"; +Driver::~Driver() { + delete tSolver; + std::cout << "~blast::Driver()\n"; } // end ~Driver -void Driver::reset() -{ - size_t nSections = sections.size(); - for (size_t iSec = 0; iSec < sections.size(); ++iSec) - sections[iSec].resize(0); - sections.resize(nSections); +void Driver::reset() { + size_t nSections = sections.size(); + for (size_t iSec = 0; iSec < sections.size(); ++iSec) + sections[iSec].resize(0); + sections.resize(nSections); } /** - * @brief Runs viscous operations. Temporal solver parametrisation is first adapted, - * Solutions are initialized than time marched towards steady state successively for each points. + * @brief Runs viscous operations. Temporal solver parametrisation is first + * adapted. Solutions are initialized than time marched towards steady state + * successively for each points. * * @return int Solver exit code. */ -int Driver::run() -{ - bool lockTrans = false; // Flag activation of transition routines. - int pointExitCode; // Output of pseudo time integration (0: converged; -1: unsuccessful, failed; >0: unsuccessful nb iter). - - double maxMach = 0.; - - for (size_t iSec = 0; iSec < sections.size(); ++iSec) - { - if (verbose > 1) - std::cout << "Sec " << iSec << " "; - - // Loop over the regions (upper, lower and wake). - int iRegion = 0; - for (auto reg: sections[iSec]) - { - convergenceStatus[iSec][iRegion].resize(0); - - if (reg->getMaxMach() > maxMach) - maxMach = reg->getMaxMach(); - - // Reset transition - if (reg->name == "wake") - reg->xtr = 0.; - else if (reg->name == "upper" || reg->name == "lower") - reg->xtr = 1.; - else - { - std::cout << "reg->name " << reg->name << std::endl; - throw std::runtime_error("Wrong region name\n"); - } - - // Reset regime. - lockTrans = false; - if (reg->name == "upper" || reg->name == "lower") - { - for (size_t k = 0; k < reg->nNodes; k++) - reg->regime[k] = 0; - reg->setStagnationBC(Re); - } - - else if (reg->name == "wake") // Wake - { - for (size_t k = 0; k < reg->nNodes; k++) - reg->regime[k] = 1; - - // Impose wake boundary condition. - std::vector<double> upperConditions(reg->getnVar(), 0.); - std::vector<double> lowerConditions(reg->getnVar(), 0.); - for (size_t k = 0; k < upperConditions.size(); ++k) - { - upperConditions[k] = sections[iSec][0]->u[(sections[iSec][0]->nNodes - 1) * sections[iSec][0]->getnVar() + k]; - lowerConditions[k] = sections[iSec][1]->u[(sections[iSec][1]->nNodes - 1) * sections[iSec][1]->getnVar() + k]; - } - reg->setWakeBC(Re, upperConditions, lowerConditions); - lockTrans = true; +int Driver::run() { + bool lockTrans = false; // Flag activation of transition routines. + int pointExitCode; // Output of pseudo time integration (0: converged; -1: + // unsuccessful, failed; >0: unsuccessful nb iter). + + double maxMach = 0.; + + for (size_t iSec = 0; iSec < sections.size(); ++iSec) { + if (verbose > 1) + std::cout << "Sec " << iSec << " "; + + // Loop over the regions (upper, lower and wake). + int iRegion = 0; + for (auto reg : sections[iSec]) { + convergenceStatus[iSec][iRegion].resize(0); + + if (reg->getMaxMach() > maxMach) + maxMach = reg->getMaxMach(); + + // Reset transition + if (reg->name == "wake") + reg->xtr = 0.; + else if (reg->name == "upper" || reg->name == "lower") + reg->xtr = 1.; + else { + std::cout << "reg->name " << reg->name << std::endl; + throw std::runtime_error("Wrong region name\n"); + } + + // Reset regime. + lockTrans = false; + if (reg->name == "upper" || reg->name == "lower") { + for (size_t k = 0; k < reg->nNodes; k++) + reg->regime[k] = 0; + reg->setStagnationBC(Re); + } + + else if (reg->name == "wake") // Wake + { + for (size_t k = 0; k < reg->nNodes; k++) + reg->regime[k] = 1; + + // Impose wake boundary condition. + std::vector<double> upperConditions(reg->getnVar(), 0.); + std::vector<double> lowerConditions(reg->getnVar(), 0.); + for (size_t k = 0; k < upperConditions.size(); ++k) { + upperConditions[k] = + sections[iSec][0]->u[(sections[iSec][0]->nNodes - 1) * + sections[iSec][0]->getnVar() + + k]; + lowerConditions[k] = + sections[iSec][1]->u[(sections[iSec][1]->nNodes - 1) * + sections[iSec][1]->getnVar() + + k]; + } + reg->setWakeBC(Re, upperConditions, lowerConditions); + lockTrans = true; + } else + throw std::runtime_error("Wrong region name\n"); + + // Loop over points + for (size_t iPoint = 1; iPoint < reg->nNodes; ++iPoint) { + // Initialize solution at point + tSolver->initialCondition(iPoint, reg); + // Solve equations + tms["1-Solver"].start(); + pointExitCode = tSolver->integration(iPoint, reg); + tms["1-Solver"].stop(); + + if (pointExitCode != 0) + convergenceStatus[iSec][iRegion].push_back(iPoint); + + // Transition + tms["2-Transition"].start(); + if (!lockTrans) { + // Forced transition + if (reg->xtrF != -1 && reg->xoc[iPoint] >= reg->xtrF) { + reg->u[iPoint * reg->getnVar() + 2] = reg->getnCrit(); + averageTransition(iPoint, reg, true); + if (verbose > 1) { + std::cout << std::fixed; + std::cout << std::setprecision(2); + std::cout << reg->xtr << " (" << reg->transitionNode << ") "; } - else - throw std::runtime_error("Wrong region name\n"); - - // Loop over points - for (size_t iPoint = 1; iPoint < reg->nNodes; ++iPoint) - { - // Initialize solution at point - tSolver->initialCondition(iPoint, reg); - // Solve equations - tms["1-Solver"].start(); - pointExitCode = tSolver->integration(iPoint, reg); - tms["1-Solver"].stop(); - - if (pointExitCode != 0) - convergenceStatus[iSec][iRegion].push_back(iPoint); - - // Transition - tms["2-Transition"].start(); - if (!lockTrans) - { - // Forced transition - if (reg->xtrF != -1 && reg->xoc[iPoint] >= reg->xtrF) - { - reg->u[iPoint * reg->getnVar() + 2] = reg->getnCrit(); - averageTransition(iPoint, reg, true); - if (verbose > 1) - { - std::cout << std::fixed; - std::cout << std::setprecision(2); - std::cout << reg->xtr - << " (" << reg->transitionNode << ") "; - } - lockTrans = true; - } - // Free transtion - else if (reg->xtrF == -1) - { - // Check if perturbation waves are growing or not. - checkWaves(iPoint, reg); - - // Amplification factor is compared to critical amplification factor. - if (reg->u[iPoint * reg->getnVar() + 2] >= reg->getnCrit()) - { - averageTransition(iPoint, reg, false); - if (verbose > 1) - { - std::cout << std::fixed; - std::cout << std::setprecision(2); - std::cout << reg->xtr - << " (" << reg->transitionNode << ") "; - } - lockTrans = true; - } - } - } - tms["2-Transition"].stop(); + lockTrans = true; + } + // Free transtion + else if (reg->xtrF == -1) { + // Check if perturbation waves are growing or not. + checkWaves(iPoint, reg); + + // Amplification factor is compared to critical amplification + // factor. + if (reg->u[iPoint * reg->getnVar() + 2] >= reg->getnCrit()) { + averageTransition(iPoint, reg, false); + if (verbose > 1) { + std::cout << std::fixed; + std::cout << std::setprecision(2); + std::cout << reg->xtr << " (" << reg->transitionNode << ") "; + } + lockTrans = true; } - tms["3-Blowing"].start(); - reg->computeBlowingVelocity(); - tms["3-Blowing"].stop(); - iRegion++; + } } - if (verbose > 1) - std::cout << std::endl; + tms["2-Transition"].stop(); + } + tms["3-Blowing"].start(); + reg->computeBlowingVelocity(); + tms["3-Blowing"].stop(); + iRegion++; } + if (verbose > 1) + std::cout << std::endl; + } - for (size_t i = 0; i < sections.size(); ++i) - computeSectionalDrag(sections[i], i); - computeTotalDrag(); + for (size_t i = 0; i < sections.size(); ++i) + computeSectionalDrag(sections[i], i); + computeTotalDrag(); - // Output information. - solverExitCode = outputStatus(maxMach); + // Output information. + solverExitCode = outputStatus(maxMach); - return solverExitCode; // exit code + return solverExitCode; // exit code } /** - * @brief Check whether or not instabilities are growing in the laminar boundary layer. + * @brief Check whether or not instabilities are growing in the laminar boundary + * layer. * * @param iPoint Marker id. * @param bl BoundaryLayer region. */ -void Driver::checkWaves(size_t iPoint, BoundaryLayer *bl) -{ - - double logRet_crit = 2.492 * std::pow(1. / (bl->Hk[iPoint] - 1), 0.43) + 0.7 * (std::tanh(14 * (1. / (bl->Hk[iPoint] - 1)) - 9.24) + 1.0); - - if (bl->Ret[iPoint] > 0) // Avoid log of negative number. - { - if (std::log10(bl->Ret[iPoint]) <= logRet_crit - 0.08) - bl->u[iPoint * bl->getnVar() + 2] = 0.; // Set N to 0 at that point if waves do not grow. - } - else - bl->u[iPoint * bl->getnVar() + 2] = 0.; // Set N to 0 at that point if waves do not grow. +void Driver::checkWaves(size_t iPoint, BoundaryLayer *bl) { + + double logRet_crit = + 2.492 * std::pow(1. / (bl->Hk[iPoint] - 1), 0.43) + + 0.7 * (std::tanh(14 * (1. / (bl->Hk[iPoint] - 1)) - 9.24) + 1.0); + + if (bl->Ret[iPoint] > 0) // Avoid log of negative number. + { + if (std::log10(bl->Ret[iPoint]) <= logRet_crit - 0.08) + bl->u[iPoint * bl->getnVar() + 2] = + 0.; // Set N to 0 at that point if waves do not grow. + } else + bl->u[iPoint * bl->getnVar() + 2] = + 0.; // Set N to 0 at that point if waves do not grow. } /** - * @brief Computes turbulent solution @ the transition point and averages solutions. + * @brief Computes turbulent solution @ the transition point and averages + * solutions. * * @param iPoint Marker id. * @param bl BoundaryLayer region. * @param forced Flag for forced transition. */ -void Driver::averageTransition(size_t iPoint, BoundaryLayer *bl, bool forced) -{ - // Averages solution on transition marker. - size_t nVar = bl->getnVar(); - - // Save laminar solution. - std::vector<double> lamSol(nVar, 0.0); - for (size_t k = 0; k < lamSol.size(); ++k) - lamSol[k] = bl->u[iPoint * nVar + k]; - - // Set up turbulent portion boundary condition. - bl->transitionNode = iPoint; // Save transition marker. - - // Loop over remaining points in the region. - for (size_t k = iPoint; k < bl->nNodes; ++k) - bl->regime[k] = 1; // Set Turbulent regime. - - bl->xtr = (bl->getnCrit() - bl->u[(iPoint - 1) * nVar + 2]) * ((bl->xoc[iPoint] - bl->xoc[iPoint-1]) / (bl->u[iPoint * nVar + 2] - bl->u[(iPoint - 1) * nVar + 2])) + bl->xoc[iPoint-1]; - - double avTurb = (bl->xoc[iPoint] - bl->xtr) / (bl->xoc[iPoint] - bl->xoc[iPoint-1]); - double avLam = 1. - avTurb; - - // std::cout << "avTurb " << avTurb << " avLam " << avLam << std::endl; - if (avTurb < 0. || avTurb > 1. || avLam < 0. || avLam > 1.) - { - bl->printSolution(iPoint); - bl->printSolution(iPoint - 1); - std::cout << "dx " << std::abs(bl->xoc[iPoint] - bl->xoc[iPoint - 1]) << std::endl; - std::cout << " (bl->u[iPoint * nVar + 2] - bl->u[(iPoint - 1) * nVar + 2]) " << (bl->u[iPoint * nVar + 2] - bl->u[(iPoint - 1) * nVar + 2]) << std::endl; - std::cout << " bl->getnCrit() - bl->u[(iPoint - 1) * nVar + 2] " << bl->getnCrit() - bl->u[(iPoint - 1) * nVar + 2] << std::endl; - std::cout << "xtr " << bl->xtr << std::endl; - std::cout << "avTurb " << avTurb << " avLam " << avLam << std::endl; - throw std::runtime_error("Transition location out of bounds."); - } - - // Impose boundary condition. - double Cteq_trans; - bl->closSolver->turbulentClosures(Cteq_trans, bl->u[(iPoint - 1) * nVar + 0], bl->u[(iPoint - 1) * nVar + 1], 0.03, bl->Ret[iPoint - 1], bl->Me[iPoint-1], bl->name); - bl->ctEq[iPoint - 1] = Cteq_trans; - bl->u[(iPoint - 1) * nVar + 4] = 0.7 * bl->ctEq[iPoint - 1]; - - // Avoid starting with ill conditioned IC for turbulent computation. (Regime was switched above). - // These initial guess values do not influence the converged solution. - bl->u[iPoint * nVar + 4] = bl->u[(iPoint - 1) * nVar + 4]; // IC of transition point = turbulent BC (imposed @ previous point). - bl->u[iPoint * nVar + 1] = 1.515; // Because we expect a significant drop of the shape factor. - - // Solve point in turbulent configuration. - int exitCode = tSolver->integration(iPoint, bl); - - if (exitCode != 0) - std::cout << "Warning: Transition point turbulent computation terminated with exit code " << exitCode << std::endl; - - // Average both solutions (Now solution @ iPoint is the turbulent solution). - bl->u[iPoint * nVar + 0] = avLam * lamSol[0] + avTurb * bl->u[(iPoint)*nVar + 0]; // Theta. - bl->u[iPoint * nVar + 1] = avLam * lamSol[1] + avTurb * bl->u[(iPoint)*nVar + 1]; // H. - bl->u[iPoint * nVar + 2] = bl->getnCrit(); // N. - bl->u[iPoint * nVar + 3] = avLam * lamSol[3] + avTurb * bl->u[(iPoint)*nVar + 3]; // ue. - bl->u[iPoint * nVar + 4] = avTurb * bl->u[(iPoint)*nVar + 4]; // Ct. - - bl->deltaStar[iPoint-1] = bl->u[(iPoint-1)*nVar + 0] * bl->u[(iPoint-1)*nVar + 1]; - bl->deltaStar[iPoint] = bl->u[iPoint * nVar + 0] * bl->u[iPoint * nVar + 1]; - - // Recompute closures. (The turbulent BC @ iPoint - 1 does not influence laminar closure relations). - std::vector<double> lamParam(8, 0.); - bl->closSolver->laminarClosures(lamParam, bl->u[(iPoint - 1) * nVar + 0], bl->u[(iPoint - 1) * nVar + 1], bl->Ret[iPoint - 1], bl->Me[iPoint-1], bl->name); - bl->Hstar[iPoint - 1] = lamParam[0]; - bl->Hstar2[iPoint - 1] = lamParam[1]; - bl->Hk[iPoint - 1] = lamParam[2]; - bl->cf[iPoint - 1] = lamParam[3]; - bl->cd[iPoint - 1] = lamParam[4]; - bl->delta[iPoint - 1] = lamParam[5]; - bl->ctEq[iPoint - 1] = lamParam[6]; - bl->us[iPoint - 1] = lamParam[7]; - - std::vector<double> turbParam(8, 0.); - bl->closSolver->turbulentClosures(turbParam, bl->u[(iPoint)*nVar + 0], bl->u[(iPoint)*nVar + 1], bl->u[(iPoint)*nVar + 4], bl->Ret[iPoint], bl->Me[iPoint], bl->name); - bl->Hstar[iPoint] = turbParam[0]; - bl->Hstar2[iPoint] = turbParam[1]; - bl->Hk[iPoint] = turbParam[2]; - bl->cf[iPoint] = turbParam[3]; - bl->cd[iPoint] = turbParam[4]; - bl->delta[iPoint] = turbParam[5]; - bl->ctEq[iPoint] = turbParam[6]; - bl->us[iPoint] = turbParam[7]; +void Driver::averageTransition(size_t iPoint, BoundaryLayer *bl, bool forced) { + // Averages solution on transition marker. + size_t nVar = bl->getnVar(); + + // Save laminar solution. + std::vector<double> lamSol(nVar, 0.0); + for (size_t k = 0; k < lamSol.size(); ++k) + lamSol[k] = bl->u[iPoint * nVar + k]; + + // Set up turbulent portion boundary condition. + bl->transitionNode = iPoint; // Save transition marker. + + // Loop over remaining points in the region. + for (size_t k = iPoint; k < bl->nNodes; ++k) + bl->regime[k] = 1; // Set Turbulent regime. + + bl->xtr = (bl->getnCrit() - bl->u[(iPoint - 1) * nVar + 2]) * + ((bl->xoc[iPoint] - bl->xoc[iPoint - 1]) / + (bl->u[iPoint * nVar + 2] - bl->u[(iPoint - 1) * nVar + 2])) + + bl->xoc[iPoint - 1]; + + double avTurb = + (bl->xoc[iPoint] - bl->xtr) / (bl->xoc[iPoint] - bl->xoc[iPoint - 1]); + double avLam = 1. - avTurb; + + // std::cout << "avTurb " << avTurb << " avLam " << avLam << std::endl; + if (avTurb < 0. || avTurb > 1. || avLam < 0. || avLam > 1.) { + bl->printSolution(iPoint); + bl->printSolution(iPoint - 1); + std::cout << "dx " << std::abs(bl->xoc[iPoint] - bl->xoc[iPoint - 1]) + << std::endl; + std::cout << " (bl->u[iPoint * nVar + 2] - bl->u[(iPoint - 1) * nVar + 2]) " + << (bl->u[iPoint * nVar + 2] - bl->u[(iPoint - 1) * nVar + 2]) + << std::endl; + std::cout << " bl->getnCrit() - bl->u[(iPoint - 1) * nVar + 2] " + << bl->getnCrit() - bl->u[(iPoint - 1) * nVar + 2] << std::endl; + std::cout << "xtr " << bl->xtr << std::endl; + std::cout << "avTurb " << avTurb << " avLam " << avLam << std::endl; + throw std::runtime_error("Transition location out of bounds."); + } + + // Impose boundary condition. + double Cteq_trans; + bl->closSolver->turbulentClosures(Cteq_trans, bl->u[(iPoint - 1) * nVar + 0], + bl->u[(iPoint - 1) * nVar + 1], 0.03, + bl->Ret[iPoint - 1], bl->Me[iPoint - 1], + bl->name); + bl->ctEq[iPoint - 1] = Cteq_trans; + bl->u[(iPoint - 1) * nVar + 4] = 0.7 * bl->ctEq[iPoint - 1]; + + // Avoid starting with ill conditioned IC for turbulent computation. (Regime + // was switched above). These initial guess values do not influence the + // converged solution. + bl->u[iPoint * nVar + 4] = + bl->u[(iPoint - 1) * nVar + 4]; // IC of transition point = turbulent BC + // (imposed @ previous point). + bl->u[iPoint * nVar + 1] = + 1.515; // Because we expect a significant drop of the shape factor. + + // Solve point in turbulent configuration. + int exitCode = tSolver->integration(iPoint, bl); + + if (exitCode != 0) + std::cout << "Warning: Transition point turbulent computation terminated " + "with exit code " + << exitCode << std::endl; + + // Average both solutions (Now solution @ iPoint is the turbulent solution). + bl->u[iPoint * nVar + 0] = + avLam * lamSol[0] + avTurb * bl->u[(iPoint)*nVar + 0]; // Theta. + bl->u[iPoint * nVar + 1] = + avLam * lamSol[1] + avTurb * bl->u[(iPoint)*nVar + 1]; // H. + bl->u[iPoint * nVar + 2] = bl->getnCrit(); // N. + bl->u[iPoint * nVar + 3] = + avLam * lamSol[3] + avTurb * bl->u[(iPoint)*nVar + 3]; // ue. + bl->u[iPoint * nVar + 4] = avTurb * bl->u[(iPoint)*nVar + 4]; // Ct. + + bl->deltaStar[iPoint - 1] = + bl->u[(iPoint - 1) * nVar + 0] * bl->u[(iPoint - 1) * nVar + 1]; + bl->deltaStar[iPoint] = bl->u[iPoint * nVar + 0] * bl->u[iPoint * nVar + 1]; + + // Recompute closures. (The turbulent BC @ iPoint - 1 does not influence + // laminar closure relations). + std::vector<double> lamParam(8, 0.); + bl->closSolver->laminarClosures( + lamParam, bl->u[(iPoint - 1) * nVar + 0], bl->u[(iPoint - 1) * nVar + 1], + bl->Ret[iPoint - 1], bl->Me[iPoint - 1], bl->name); + bl->Hstar[iPoint - 1] = lamParam[0]; + bl->Hstar2[iPoint - 1] = lamParam[1]; + bl->Hk[iPoint - 1] = lamParam[2]; + bl->cf[iPoint - 1] = lamParam[3]; + bl->cd[iPoint - 1] = lamParam[4]; + bl->delta[iPoint - 1] = lamParam[5]; + bl->ctEq[iPoint - 1] = lamParam[6]; + bl->us[iPoint - 1] = lamParam[7]; + + std::vector<double> turbParam(8, 0.); + bl->closSolver->turbulentClosures( + turbParam, bl->u[(iPoint)*nVar + 0], bl->u[(iPoint)*nVar + 1], + bl->u[(iPoint)*nVar + 4], bl->Ret[iPoint], bl->Me[iPoint], bl->name); + bl->Hstar[iPoint] = turbParam[0]; + bl->Hstar2[iPoint] = turbParam[1]; + bl->Hk[iPoint] = turbParam[2]; + bl->cf[iPoint] = turbParam[3]; + bl->cd[iPoint] = turbParam[4]; + bl->delta[iPoint] = turbParam[5]; + bl->ctEq[iPoint] = turbParam[6]; + bl->us[iPoint] = turbParam[7]; } /** - * @brief Friction, pressure and total drag computation at each station of the configuration. + * @brief Friction, pressure and total drag computation at each station of the + * configuration. * * @tparam Cdt = theta * Ue^((H+5)/2). * @tparam Cdf = integral(Cf dx)_upper + integral(Cf dx)_lower. @@ -336,52 +356,56 @@ void Driver::averageTransition(size_t iPoint, BoundaryLayer *bl, bool forced) * @param bl BoundaryLayer region. * @param i Considered section. */ -void Driver::computeSectionalDrag(std::vector<BoundaryLayer *> const &sec, size_t i) -{ - size_t nVar = sec[0]->getnVar(); - - // Normalize friction and dissipation coefficients. - std::vector<double> frictioncoeff_upper(sec[0]->nNodes, 0.0); - for (size_t k = 0; k < frictioncoeff_upper.size(); ++k) - frictioncoeff_upper[k] = sec[0]->vt[k] * sec[0]->vt[k] * sec[0]->cf[k]; - - std::vector<double> frictioncoeff_lower(sec[1]->nNodes, 0.0); - for (size_t k = 0; k < frictioncoeff_lower.size(); ++k) - frictioncoeff_lower[k] = sec[1]->vt[k] * sec[1]->vt[k] * sec[1]->cf[k]; - - // Compute friction drag coefficient. - double Cdf_upper = 0.0; - for (size_t k = 1; k < sec[0]->nNodes; ++k) - Cdf_upper += (frictioncoeff_upper[k] + frictioncoeff_upper[k - 1]) * (sec[0]->x[k] - sec[0]->x[k-1]) / 2; - double Cdf_lower = 0.0; - for (size_t k = 1; k < sec[1]->nNodes; ++k) - Cdf_lower += (frictioncoeff_lower[k] + frictioncoeff_lower[k - 1]) * (sec[1]->x[k] - sec[1]->x[k-1]) / 2; - Cdf_sec[i] = Cdf_upper + Cdf_lower; // No friction in the wake - - // Total drag coefficient. Computed from upper and lower TE if there is no wake. - if (sec.size() > 2 && sec[2]->getName() == "wake") - { - size_t lastWkPt = (sec[2]->nNodes - 1) * nVar; - Cdt_sec[i] = 2 * sec[2]->u[lastWkPt + 0] * pow(sec[2]->u[lastWkPt + 3], (sec[2]->u[lastWkPt + 1] + 5) / 2); - } - else - { - size_t lastUpPt = (sec[0]->nNodes - 1) * nVar; - size_t lastLwPt = (sec[1]->nNodes - 1) * nVar; - Cdt_sec[i] = sec[0]->u[lastUpPt + 0] * pow(sec[0]->u[lastUpPt + 3], (sec[0]->u[lastUpPt + 1] + 5) / 2) + - sec[1]->u[lastLwPt + 0] * pow(sec[1]->u[lastLwPt + 3], (sec[1]->u[lastLwPt + 1] + 5) / 2); - } - // Pressure drag coefficient. - Cdp_sec[i] = Cdt_sec[i] - Cdf_sec[i]; +void Driver::computeSectionalDrag(std::vector<BoundaryLayer *> const &sec, + size_t i) { + size_t nVar = sec[0]->getnVar(); + + // Normalize friction and dissipation coefficients. + std::vector<double> frictioncoeff_upper(sec[0]->nNodes, 0.0); + for (size_t k = 0; k < frictioncoeff_upper.size(); ++k) + frictioncoeff_upper[k] = sec[0]->vt[k] * sec[0]->vt[k] * sec[0]->cf[k]; + + std::vector<double> frictioncoeff_lower(sec[1]->nNodes, 0.0); + for (size_t k = 0; k < frictioncoeff_lower.size(); ++k) + frictioncoeff_lower[k] = sec[1]->vt[k] * sec[1]->vt[k] * sec[1]->cf[k]; + + // Compute friction drag coefficient. + double Cdf_upper = 0.0; + for (size_t k = 1; k < sec[0]->nNodes; ++k) + Cdf_upper += (frictioncoeff_upper[k] + frictioncoeff_upper[k - 1]) * + (sec[0]->x[k] - sec[0]->x[k - 1]) / 2; + double Cdf_lower = 0.0; + for (size_t k = 1; k < sec[1]->nNodes; ++k) + Cdf_lower += (frictioncoeff_lower[k] + frictioncoeff_lower[k - 1]) * + (sec[1]->x[k] - sec[1]->x[k - 1]) / 2; + Cdf_sec[i] = Cdf_upper + Cdf_lower; // No friction in the wake + + // Total drag coefficient. Computed from upper and lower TE if there is no + // wake. + if (sec.size() > 2 && sec[2]->getName() == "wake") { + size_t lastWkPt = (sec[2]->nNodes - 1) * nVar; + Cdt_sec[i] = + 2 * sec[2]->u[lastWkPt + 0] * + pow(sec[2]->u[lastWkPt + 3], (sec[2]->u[lastWkPt + 1] + 5) / 2); + } else { + size_t lastUpPt = (sec[0]->nNodes - 1) * nVar; + size_t lastLwPt = (sec[1]->nNodes - 1) * nVar; + Cdt_sec[i] = + sec[0]->u[lastUpPt + 0] * + pow(sec[0]->u[lastUpPt + 3], (sec[0]->u[lastUpPt + 1] + 5) / 2) + + sec[1]->u[lastLwPt + 0] * + pow(sec[1]->u[lastLwPt + 3], (sec[1]->u[lastLwPt + 1] + 5) / 2); + } + // Pressure drag coefficient. + Cdp_sec[i] = Cdt_sec[i] - Cdf_sec[i]; } -double Driver::getAverageTransition(size_t const iRegion) const -{ - double xtr = 0.0; - for (size_t iSec = 0; iSec < sections.size(); ++iSec) - xtr += sections[iSec][iRegion]->xtr; - xtr /= sections.size(); - return xtr; +double Driver::getAverageTransition(size_t const iRegion) const { + double xtr = 0.0; + for (size_t iSec = 0; iSec < sections.size(); ++iSec) + xtr += sections[iSec][iRegion]->xtr; + xtr /= sections.size(); + return xtr; } /** @@ -389,35 +413,30 @@ double Driver::getAverageTransition(size_t const iRegion) const * Performs the sectional drag integration for 3D computations. * */ -void Driver::computeTotalDrag() -{ - Cdt = 0.; - Cdf = 0.; - Cdp = 0.; - - if (sections.size() == 1 || span == 0.) - { - Cdt = Cdt_sec[0]; - Cdf = Cdf_sec[0]; - Cdp = Cdp_sec[0]; - } - else - { - Cdt += (sections[0][0]->z[0] - 0) * Cdt_sec[0]; - Cdp += (sections[0][0]->z[0] - 0) * Cdp_sec[0]; - Cdf += (sections[0][0]->z[0] - 0) * Cdf_sec[0]; - double dz = 0.; - for (size_t k = 1; k < sections.size(); ++k) - { - dz = (sections[k][0]->z[0] - sections[k - 1][0]->z[0]); - Cdt += dz * Cdt_sec[k]; - Cdp += dz * Cdp_sec[k]; - Cdf += dz * Cdf_sec[k]; - } - Cdt /= span; - Cdp /= span; - Cdf /= span; +void Driver::computeTotalDrag() { + Cdt = 0.; + Cdf = 0.; + Cdp = 0.; + + if (sections.size() == 1 || span == 0.) { + Cdt = Cdt_sec[0]; + Cdf = Cdf_sec[0]; + Cdp = Cdp_sec[0]; + } else { + Cdt += (sections[0][0]->z[0] - 0) * Cdt_sec[0]; + Cdp += (sections[0][0]->z[0] - 0) * Cdp_sec[0]; + Cdf += (sections[0][0]->z[0] - 0) * Cdf_sec[0]; + double dz = 0.; + for (size_t k = 1; k < sections.size(); ++k) { + dz = (sections[k][0]->z[0] - sections[k - 1][0]->z[0]); + Cdt += dz * Cdt_sec[k]; + Cdp += dz * Cdp_sec[k]; + Cdf += dz * Cdf_sec[k]; } + Cdt /= span; + Cdp /= span; + Cdf /= span; + } } /** @@ -426,185 +445,183 @@ void Driver::computeTotalDrag() * @param maxMach Maximum Mach number identified on the configuration. * @return int Solver exit code (0 converged, !=0 not converged). */ -int Driver::outputStatus(double maxMach) const -{ - int solverExitCode = 0; - for (size_t iSec = 0; iSec < sections.size(); ++iSec) - for (size_t iReg = 0; iReg < sections[iSec].size(); ++iReg) - if (convergenceStatus[iSec][iReg].size() != 0) - { - solverExitCode = -1; - break; - } - - if (verbose > 2 && solverExitCode != 0) - { - // Output unconverged points. - std::cout << "Unconverged points" << std::endl; - std::cout << std::setw(10) << "Section" - << std::setw(12) << "Region" - << std::setw(16) << "Markers" << std::endl; - for (size_t iSec = 0; iSec < sections.size(); ++iSec) - { - unsigned int count = 0; - for (size_t iReg = 0; iReg < sections[iSec].size(); ++iReg) - { - std::cout << std::setw(10) << iSec; - std::cout << std::setw(12) << iReg << " "; - if (convergenceStatus[iSec][iReg].size() != 0) - for (size_t iPoint = 0; iPoint < convergenceStatus[iSec][iReg].size(); ++iPoint) - { - std::cout << convergenceStatus[iSec][iReg][iPoint] << " (" << sections[iSec][iReg]->x[convergenceStatus[iSec][iReg][iPoint]] << "), "; - ++count; - } - std::cout << "\n"; - } - std::cout << "total: " << count << "\n"; - } - std::cout << "" << std::endl; +int Driver::outputStatus(double maxMach) const { + int solverExitCode = 0; + for (size_t iSec = 0; iSec < sections.size(); ++iSec) + for (size_t iReg = 0; iReg < sections[iSec].size(); ++iReg) + if (convergenceStatus[iSec][iReg].size() != 0) { + solverExitCode = -1; + break; + } + + if (verbose > 2 && solverExitCode != 0) { + // Output unconverged points. + std::cout << "Unconverged points" << std::endl; + std::cout << std::setw(10) << "Section" << std::setw(12) << "Region" + << std::setw(16) << "Markers" << std::endl; + for (size_t iSec = 0; iSec < sections.size(); ++iSec) { + unsigned int count = 0; + for (size_t iReg = 0; iReg < sections[iSec].size(); ++iReg) { + std::cout << std::setw(10) << iSec; + std::cout << std::setw(12) << iReg << " "; + if (convergenceStatus[iSec][iReg].size() != 0) + for (size_t iPoint = 0; iPoint < convergenceStatus[iSec][iReg].size(); + ++iPoint) { + std::cout << convergenceStatus[iSec][iReg][iPoint] << " (" + << sections[iSec][iReg] + ->x[convergenceStatus[iSec][iReg][iPoint]] + << "), "; + ++count; + } + std::cout << "\n"; + } + std::cout << "total: " << count << "\n"; } + std::cout << "" << std::endl; + } - if (verbose > 0) - { - // Compute mean transition locations. - std::vector<double> meanTransitions(2, 0.); - for (size_t iSec = 0; iSec < sections.size(); ++iSec) - for (size_t iReg = 0; iReg < 2; ++iReg) - meanTransitions[iReg] += sections[iSec][iReg]->xtr; - for (size_t iReg = 0; iReg < meanTransitions.size(); ++iReg) - meanTransitions[iReg] /= sections.size(); - - std::cout << std::fixed << std::setprecision(2) - << "Viscous solver for Re " << Re / 1e6 << "e6, Mach max " - << maxMach - << std::endl; - - std::cout << std::setw(10) << "xTr Upper" - << std::setw(12) << "xTr Lower" - << std::setw(12) << "Cd" << std::endl; - std::cout << std::fixed << std::setprecision(2); - std::cout << std::setw(10) << meanTransitions[0] - << std::setw(12) << meanTransitions[1]; - std::cout << std::fixed << std::setprecision(5); - std::cout << std::setw(12) << Cdt << "\n"; - - if (verbose > 0) - { - if (solverExitCode == 0) - std::cout << ANSI_COLOR_GREEN << "Viscous solver converged." << ANSI_COLOR_RESET << std::endl; - else - std::cout << ANSI_COLOR_YELLOW << "Viscous solver not converged." << ANSI_COLOR_RESET << std::endl; - } + if (verbose > 0) { + // Compute mean transition locations. + std::vector<double> meanTransitions(2, 0.); + for (size_t iSec = 0; iSec < sections.size(); ++iSec) + for (size_t iReg = 0; iReg < 2; ++iReg) + meanTransitions[iReg] += sections[iSec][iReg]->xtr; + for (size_t iReg = 0; iReg < meanTransitions.size(); ++iReg) + meanTransitions[iReg] /= sections.size(); + + std::cout << std::fixed << std::setprecision(2) << "Viscous solver for Re " + << Re / 1e6 << "e6, Mach max " << maxMach << std::endl; + + std::cout << std::setw(10) << "xTr Upper" << std::setw(12) << "xTr Lower" + << std::setw(12) << "Cd" << std::endl; + std::cout << std::fixed << std::setprecision(2); + std::cout << std::setw(10) << meanTransitions[0] << std::setw(12) + << meanTransitions[1]; + std::cout << std::fixed << std::setprecision(5); + std::cout << std::setw(12) << Cdt << "\n"; + + if (verbose > 0) { + if (solverExitCode == 0) + std::cout << ANSI_COLOR_GREEN << "Viscous solver converged." + << ANSI_COLOR_RESET << std::endl; + else + std::cout << ANSI_COLOR_YELLOW << "Viscous solver not converged." + << ANSI_COLOR_RESET << std::endl; + } - if (verbose > 2) - { - std::cout << "Viscous solver CPU" << std::endl - << tms; - } + if (verbose > 2) { + std::cout << "Viscous solver CPU" << std::endl << tms; } + } - if (verbose > 0) - std::cout << "" << std::endl; - return solverExitCode; + if (verbose > 0) + std::cout << "" << std::endl; + return solverExitCode; } /** - * @brief Returns the integral boundary layer solution in a section (sorted from upper Te to lower Te than wake). + * @brief Returns the integral boundary layer solution in a section (sorted from + * upper Te to lower Te than wake). * * @param iSec id of the considered section. * @return std::vector<std::vector<double>> */ -std::vector<std::vector<double>> Driver::getSolution(size_t iSec) -{ - size_t nMarkersUp = sections[iSec][0]->nNodes; - size_t nMarkersLw = sections[iSec][1]->nNodes; // No stagnation point doublon. - size_t nVar = sections[iSec][0]->getnVar(); - - std::vector<std::vector<double>> Sln(20); - for (size_t iVector = 0; iVector < Sln.size(); ++iVector) - Sln[iVector].resize(nMarkersUp + nMarkersLw + sections[iSec][2]->nNodes, 0.); - // Upper side. - size_t revPoint = nMarkersUp - 1; - for (size_t iPoint = 0; iPoint < nMarkersUp; ++iPoint) - { - Sln[0][iPoint] = sections[iSec][0]->u[revPoint * nVar + 0]; - Sln[1][iPoint] = sections[iSec][0]->u[revPoint * nVar + 1]; - Sln[2][iPoint] = sections[iSec][0]->u[revPoint * nVar + 2]; - Sln[3][iPoint] = sections[iSec][0]->u[revPoint * nVar + 3]; - Sln[4][iPoint] = sections[iSec][0]->u[revPoint * nVar + 4]; - Sln[5][iPoint] = sections[iSec][0]->deltaStar[revPoint]; - - Sln[6][iPoint] = sections[iSec][0]->Ret[revPoint]; - Sln[7][iPoint] = sections[iSec][0]->cd[revPoint]; - Sln[8][iPoint] = sections[iSec][0]->cf[revPoint]; - Sln[9][iPoint] = sections[iSec][0]->Hstar[revPoint]; - Sln[10][iPoint] = sections[iSec][0]->Hstar2[revPoint]; - Sln[11][iPoint] = sections[iSec][0]->Hk[revPoint]; - Sln[12][iPoint] = sections[iSec][0]->ctEq[revPoint]; - Sln[13][iPoint] = sections[iSec][0]->us[revPoint]; - Sln[14][iPoint] = sections[iSec][0]->delta[revPoint]; - - Sln[15][iPoint] = sections[iSec][0]->x[revPoint]; - Sln[16][iPoint] = sections[iSec][0]->xoc[revPoint]; - Sln[17][iPoint] = sections[iSec][0]->y[revPoint]; - Sln[18][iPoint] = sections[iSec][0]->z[revPoint]; - Sln[19][iPoint] = sections[iSec][0]->vt[revPoint]; - --revPoint; - } - // Lower side. - for (size_t iPoint = 0; iPoint < sections[iSec][1]->nNodes; ++iPoint) - { - Sln[0][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 0]; - Sln[1][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 1]; - Sln[2][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 2]; - Sln[3][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 3]; - Sln[4][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 4]; - Sln[5][nMarkersUp + iPoint] = sections[iSec][1]->deltaStar[iPoint]; - - Sln[6][nMarkersUp + iPoint] = sections[iSec][1]->Ret[iPoint]; - Sln[7][nMarkersUp + iPoint] = sections[iSec][1]->cd[iPoint]; - Sln[8][nMarkersUp + iPoint] = sections[iSec][1]->cf[iPoint]; - Sln[9][nMarkersUp + iPoint] = sections[iSec][1]->Hstar[iPoint]; - Sln[10][nMarkersUp + iPoint] = sections[iSec][1]->Hstar2[iPoint]; - Sln[11][nMarkersUp + iPoint] = sections[iSec][1]->Hk[iPoint]; - Sln[12][nMarkersUp + iPoint] = sections[iSec][1]->ctEq[iPoint]; - Sln[13][nMarkersUp + iPoint] = sections[iSec][1]->us[iPoint]; - Sln[14][nMarkersUp + iPoint] = sections[iSec][1]->delta[iPoint]; - - Sln[15][nMarkersUp + iPoint] = sections[iSec][1]->x[iPoint]; - Sln[16][nMarkersUp + iPoint] = sections[iSec][1]->xoc[iPoint]; - Sln[17][nMarkersUp + iPoint] = sections[iSec][1]->y[iPoint]; - Sln[18][nMarkersUp + iPoint] = sections[iSec][1]->z[iPoint]; - Sln[19][nMarkersUp + iPoint] = sections[iSec][1]->vt[iPoint]; - } - // Wake. - for (size_t iPoint = 0; iPoint < sections[iSec][2]->nNodes; ++iPoint) - { - Sln[0][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->u[iPoint * nVar + 0]; - Sln[1][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->u[iPoint * nVar + 1]; - Sln[2][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->u[iPoint * nVar + 2]; - Sln[3][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->u[iPoint * nVar + 3]; - Sln[4][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->u[iPoint * nVar + 4]; - Sln[5][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->deltaStar[iPoint]; - - Sln[6][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->Ret[iPoint]; - Sln[7][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->cd[iPoint]; - Sln[8][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->cf[iPoint]; - Sln[9][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->Hstar[iPoint]; - Sln[10][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->Hstar2[iPoint]; - Sln[11][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->Hk[iPoint]; - Sln[12][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->ctEq[iPoint]; - Sln[13][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->us[iPoint]; - Sln[14][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->delta[iPoint]; - - Sln[15][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->x[iPoint]; - Sln[16][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->xoc[iPoint]; - Sln[17][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->y[iPoint]; - Sln[18][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->z[iPoint]; - Sln[19][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->vt[iPoint]; - } - - if (verbose > 2) - std::cout << "Solution structure sent." << std::endl; - return Sln; +std::vector<std::vector<double>> Driver::getSolution(size_t iSec) { + size_t nMarkersUp = sections[iSec][0]->nNodes; + size_t nMarkersLw = sections[iSec][1]->nNodes; // No stagnation point doublon. + size_t nVar = sections[iSec][0]->getnVar(); + + std::vector<std::vector<double>> Sln(20); + for (size_t iVector = 0; iVector < Sln.size(); ++iVector) + Sln[iVector].resize(nMarkersUp + nMarkersLw + sections[iSec][2]->nNodes, + 0.); + // Upper side. + size_t revPoint = nMarkersUp - 1; + for (size_t iPoint = 0; iPoint < nMarkersUp; ++iPoint) { + Sln[0][iPoint] = sections[iSec][0]->u[revPoint * nVar + 0]; + Sln[1][iPoint] = sections[iSec][0]->u[revPoint * nVar + 1]; + Sln[2][iPoint] = sections[iSec][0]->u[revPoint * nVar + 2]; + Sln[3][iPoint] = sections[iSec][0]->u[revPoint * nVar + 3]; + Sln[4][iPoint] = sections[iSec][0]->u[revPoint * nVar + 4]; + Sln[5][iPoint] = sections[iSec][0]->deltaStar[revPoint]; + + Sln[6][iPoint] = sections[iSec][0]->Ret[revPoint]; + Sln[7][iPoint] = sections[iSec][0]->cd[revPoint]; + Sln[8][iPoint] = sections[iSec][0]->cf[revPoint]; + Sln[9][iPoint] = sections[iSec][0]->Hstar[revPoint]; + Sln[10][iPoint] = sections[iSec][0]->Hstar2[revPoint]; + Sln[11][iPoint] = sections[iSec][0]->Hk[revPoint]; + Sln[12][iPoint] = sections[iSec][0]->ctEq[revPoint]; + Sln[13][iPoint] = sections[iSec][0]->us[revPoint]; + Sln[14][iPoint] = sections[iSec][0]->delta[revPoint]; + + Sln[15][iPoint] = sections[iSec][0]->x[revPoint]; + Sln[16][iPoint] = sections[iSec][0]->xoc[revPoint]; + Sln[17][iPoint] = sections[iSec][0]->y[revPoint]; + Sln[18][iPoint] = sections[iSec][0]->z[revPoint]; + Sln[19][iPoint] = sections[iSec][0]->vt[revPoint]; + --revPoint; + } + // Lower side. + for (size_t iPoint = 0; iPoint < sections[iSec][1]->nNodes; ++iPoint) { + Sln[0][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 0]; + Sln[1][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 1]; + Sln[2][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 2]; + Sln[3][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 3]; + Sln[4][nMarkersUp + iPoint] = sections[iSec][1]->u[iPoint * nVar + 4]; + Sln[5][nMarkersUp + iPoint] = sections[iSec][1]->deltaStar[iPoint]; + + Sln[6][nMarkersUp + iPoint] = sections[iSec][1]->Ret[iPoint]; + Sln[7][nMarkersUp + iPoint] = sections[iSec][1]->cd[iPoint]; + Sln[8][nMarkersUp + iPoint] = sections[iSec][1]->cf[iPoint]; + Sln[9][nMarkersUp + iPoint] = sections[iSec][1]->Hstar[iPoint]; + Sln[10][nMarkersUp + iPoint] = sections[iSec][1]->Hstar2[iPoint]; + Sln[11][nMarkersUp + iPoint] = sections[iSec][1]->Hk[iPoint]; + Sln[12][nMarkersUp + iPoint] = sections[iSec][1]->ctEq[iPoint]; + Sln[13][nMarkersUp + iPoint] = sections[iSec][1]->us[iPoint]; + Sln[14][nMarkersUp + iPoint] = sections[iSec][1]->delta[iPoint]; + + Sln[15][nMarkersUp + iPoint] = sections[iSec][1]->x[iPoint]; + Sln[16][nMarkersUp + iPoint] = sections[iSec][1]->xoc[iPoint]; + Sln[17][nMarkersUp + iPoint] = sections[iSec][1]->y[iPoint]; + Sln[18][nMarkersUp + iPoint] = sections[iSec][1]->z[iPoint]; + Sln[19][nMarkersUp + iPoint] = sections[iSec][1]->vt[iPoint]; + } + // Wake. + for (size_t iPoint = 0; iPoint < sections[iSec][2]->nNodes; ++iPoint) { + Sln[0][nMarkersUp + nMarkersLw + iPoint] = + sections[iSec][2]->u[iPoint * nVar + 0]; + Sln[1][nMarkersUp + nMarkersLw + iPoint] = + sections[iSec][2]->u[iPoint * nVar + 1]; + Sln[2][nMarkersUp + nMarkersLw + iPoint] = + sections[iSec][2]->u[iPoint * nVar + 2]; + Sln[3][nMarkersUp + nMarkersLw + iPoint] = + sections[iSec][2]->u[iPoint * nVar + 3]; + Sln[4][nMarkersUp + nMarkersLw + iPoint] = + sections[iSec][2]->u[iPoint * nVar + 4]; + Sln[5][nMarkersUp + nMarkersLw + iPoint] = + sections[iSec][2]->deltaStar[iPoint]; + + Sln[6][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->Ret[iPoint]; + Sln[7][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->cd[iPoint]; + Sln[8][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->cf[iPoint]; + Sln[9][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->Hstar[iPoint]; + Sln[10][nMarkersUp + nMarkersLw + iPoint] = + sections[iSec][2]->Hstar2[iPoint]; + Sln[11][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->Hk[iPoint]; + Sln[12][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->ctEq[iPoint]; + Sln[13][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->us[iPoint]; + Sln[14][nMarkersUp + nMarkersLw + iPoint] = + sections[iSec][2]->delta[iPoint]; + + Sln[15][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->x[iPoint]; + Sln[16][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->xoc[iPoint]; + Sln[17][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->y[iPoint]; + Sln[18][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->z[iPoint]; + Sln[19][nMarkersUp + nMarkersLw + iPoint] = sections[iSec][2]->vt[iPoint]; + } + + if (verbose > 2) + std::cout << "Solution structure sent." << std::endl; + return Sln; } \ No newline at end of file diff --git a/blast/src/DDriver.h b/blast/src/DDriver.h index c04b1e8..1ff4ba2 100644 --- a/blast/src/DDriver.h +++ b/blast/src/DDriver.h @@ -1,64 +1,69 @@ #ifndef DDRIVER_H #define DDRIVER_H +#include "DBoundaryLayer.h" #include "blast.h" #include "wObject.h" -#include "DBoundaryLayer.h" #include "wTimers.h" -namespace blast -{ +namespace blast { /** - * @brief Boundary layer solver driver. Performs the space marching and set up time marching for each point. + * @brief Boundary layer solver driver. Performs the space marching and set up + * time marching for each point. * @authors Paul Dechamps */ -class BLAST_API Driver : public fwk::wSharedObject -{ +class BLAST_API Driver : public fwk::wSharedObject { public: - double Cdt; ///< Total drag coefficient. - double Cdf; ///< Total friction drag coefficient. - double Cdp; ///< Total pressure drag coefficient. - std::vector<double> Cdt_sec; ///< Sectional total drag coefficient. - std::vector<double> Cdf_sec; ///< Sectional friction drag coefficient. - std::vector<double> Cdp_sec; ///< Sectional pressure drag coefficient. - std::vector<std::vector<BoundaryLayer *>> sections; ///< Boundary layer regions sorted by section. - unsigned int verbose; ///< Verbosity level of the solver 0<=verbose<=1. + double Cdt; ///< Total drag coefficient. + double Cdf; ///< Total friction drag coefficient. + double Cdp; ///< Total pressure drag coefficient. + std::vector<double> Cdt_sec; ///< Sectional total drag coefficient. + std::vector<double> Cdf_sec; ///< Sectional friction drag coefficient. + std::vector<double> Cdp_sec; ///< Sectional pressure drag coefficient. + std::vector<std::vector<BoundaryLayer *>> + sections; ///< Boundary layer regions sorted by section. + unsigned int verbose; ///< Verbosity level of the solver 0<=verbose<=1. private: - double Re; ///< Freestream Reynolds number. - double CFL0; ///< Initial CFL number for pseudo time integration. - double span; ///< Wing Span (Used only for drag computation, not used if 2D case). - Solver *tSolver; ///< Pseudo-time solver. - int solverExitCode; ///< Exit code of viscous calculations. - std::vector<std::vector<std::vector<size_t>>> convergenceStatus; ///< Vector containing points that did not converged. + double Re; ///< Freestream Reynolds number. + double CFL0; ///< Initial CFL number for pseudo time integration. + double span; ///< Wing Span (Used only for drag computation, not used if 2D + ///< case). + Solver *tSolver; ///< Pseudo-time solver. + int solverExitCode; ///< Exit code of viscous calculations. + std::vector<std::vector<std::vector<size_t>>> + convergenceStatus; ///< Vector containing points that did not converged. protected: - fwk::Timers tms; ///< Internal timers + fwk::Timers tms; ///< Internal timers public: - Driver(double _Re, double _Minf, double _CFL0, size_t nSections, - double xtrF_top=-1., double xtrF_bot=-1., double _span = 0., unsigned int _verbose = 1); - ~Driver(); - int run(); - void reset(); + Driver(double _Re, double _Minf, double _CFL0, size_t nSections, + double xtrF_top = -1., double xtrF_bot = -1., double _span = 0., + unsigned int _verbose = 1); + ~Driver(); + int run(); + void reset(); - // Getters. - double getAverageTransition(size_t const iRegion) const; - double getRe() const { return Re; }; - std::vector<std::vector<double>> getSolution(size_t iSec); + // Getters. + double getAverageTransition(size_t const iRegion) const; + double getRe() const { return Re; }; + std::vector<std::vector<double>> getSolution(size_t iSec); - // Setters. - void setVerbose(unsigned int _verbose) { verbose = _verbose; }; + // Setters. + void setVerbose(unsigned int _verbose) { verbose = _verbose; }; - void addSection(size_t iSec, BoundaryLayer * &bl){sections[iSec].push_back(bl);}; + void addSection(size_t iSec, BoundaryLayer *&bl) { + sections[iSec].push_back(bl); + }; private: - void checkWaves(size_t iPoint, BoundaryLayer *bl); - void averageTransition(size_t iPoint, BoundaryLayer *bl, bool forced); - void computeSectionalDrag(std::vector<BoundaryLayer *> const &bl, size_t i); - void computeTotalDrag(); - void computeBlwVel(); - int outputStatus(double maxMach) const; + void checkWaves(size_t iPoint, BoundaryLayer *bl); + void averageTransition(size_t iPoint, BoundaryLayer *bl, bool forced); + void computeSectionalDrag(std::vector<BoundaryLayer *> const &bl, size_t i); + void computeTotalDrag(); + void computeBlwVel(); + int outputStatus(double maxMach) const; }; } // namespace blast #endif // DDRIVER_H diff --git a/blast/src/DFluxes.cpp b/blast/src/DFluxes.cpp index 168b60e..4f33a13 100644 --- a/blast/src/DFluxes.cpp +++ b/blast/src/DFluxes.cpp @@ -12,13 +12,12 @@ using namespace Eigen; * @param bl Boundary layer region. * @return VectorXd */ -VectorXd Fluxes::computeResiduals(size_t iPoint, BoundaryLayer *bl) -{ - size_t nVar = bl->getnVar(); - std::vector<double> u(nVar, 0.); - for (size_t k = 0; k < nVar; ++k) - u[k] = bl->u[iPoint * nVar + k]; - return blLaws(iPoint, bl, u); +VectorXd Fluxes::computeResiduals(size_t iPoint, BoundaryLayer *bl) { + size_t nVar = bl->getnVar(); + std::vector<double> u(nVar, 0.); + for (size_t k = 0; k < nVar; ++k) + u[k] = bl->u[iPoint * nVar + k]; + return blLaws(iPoint, bl, u); } /** @@ -30,23 +29,22 @@ VectorXd Fluxes::computeResiduals(size_t iPoint, BoundaryLayer *bl) * @param eps Pertubation from current solution used to compute the Jacobian. * @return MatrixXd */ -MatrixXd Fluxes::computeJacobian(size_t iPoint, BoundaryLayer *bl, VectorXd const &sysRes, double eps) -{ - size_t nVar = bl->getnVar(); - MatrixXd JacMatrix = MatrixXd::Zero(5, 5); - std::vector<double> uUp(nVar, 0.); - for (size_t k = 0; k < nVar; ++k) - uUp[k] = bl->u[iPoint * nVar + k]; +MatrixXd Fluxes::computeJacobian(size_t iPoint, BoundaryLayer *bl, + VectorXd const &sysRes, double eps) { + size_t nVar = bl->getnVar(); + MatrixXd JacMatrix = MatrixXd::Zero(5, 5); + std::vector<double> uUp(nVar, 0.); + for (size_t k = 0; k < nVar; ++k) + uUp[k] = bl->u[iPoint * nVar + k]; - double varSave = 0.; - for (size_t iVar = 0; iVar < nVar; ++iVar) - { - varSave = uUp[iVar]; - uUp[iVar] += eps; - JacMatrix.col(iVar) = (blLaws(iPoint, bl, uUp) - sysRes) / eps; - uUp[iVar] = varSave; - } - return JacMatrix; + double varSave = 0.; + for (size_t iVar = 0; iVar < nVar; ++iVar) { + varSave = uUp[iVar]; + uUp[iVar] += eps; + JacMatrix.col(iVar) = (blLaws(iPoint, bl, uUp) - sysRes) / eps; + uUp[iVar] = varSave; + } + return JacMatrix; } /** @@ -57,148 +55,230 @@ MatrixXd Fluxes::computeJacobian(size_t iPoint, BoundaryLayer *bl, VectorXd cons * @param u Solution vector at point iPoint. * @return VectorXd */ -VectorXd Fluxes::blLaws(size_t iPoint, BoundaryLayer *bl, std::vector<double> u) -{ - size_t nVar = bl->getnVar(); +VectorXd Fluxes::blLaws(size_t iPoint, BoundaryLayer *bl, + std::vector<double> u) { + size_t nVar = bl->getnVar(); - // Dissipation ratio. - double dissipRatio = 0.; - if (bl->name == "wake") - dissipRatio = 0.9; - else - dissipRatio = 1.; + // Dissipation ratio. + double dissipRatio = 0.; + if (bl->name == "wake") + dissipRatio = 0.9; + else + dissipRatio = 1.; - bl->Ret[iPoint] = std::max(u[3] * u[0] * Re, 1.0); // Reynolds number based on theta. - bl->deltaStar[iPoint] = u[0] * u[1]; // Displacement thickness. + bl->Ret[iPoint] = + std::max(u[3] * u[0] * Re, 1.0); // Reynolds number based on theta. + bl->deltaStar[iPoint] = u[0] * u[1]; // Displacement thickness. - // Boundary layer closure relations. - if (bl->regime[iPoint] == 0) - { - // Laminar closure relations. - std::vector<double> lamParam(8, 0.); - bl->closSolver->laminarClosures(lamParam, u[0], u[1], bl->Ret[iPoint], bl->Me[iPoint], bl->name); - bl->Hstar[iPoint] = lamParam[0]; - bl->Hstar2[iPoint] = lamParam[1]; - bl->Hk[iPoint] = lamParam[2]; - bl->cf[iPoint] = lamParam[3]; - bl->cd[iPoint] = lamParam[4]; - bl->delta[iPoint] = lamParam[5]; - bl->ctEq[iPoint] = lamParam[6]; - bl->us[iPoint] = lamParam[7]; - } + // Boundary layer closure relations. + if (bl->regime[iPoint] == 0) { + // Laminar closure relations. + std::vector<double> lamParam(8, 0.); + bl->closSolver->laminarClosures(lamParam, u[0], u[1], bl->Ret[iPoint], + bl->Me[iPoint], bl->name); + bl->Hstar[iPoint] = lamParam[0]; + bl->Hstar2[iPoint] = lamParam[1]; + bl->Hk[iPoint] = lamParam[2]; + bl->cf[iPoint] = lamParam[3]; + bl->cd[iPoint] = lamParam[4]; + bl->delta[iPoint] = lamParam[5]; + bl->ctEq[iPoint] = lamParam[6]; + bl->us[iPoint] = lamParam[7]; + } - else if (bl->regime[iPoint] == 1) - { - // Turbulent closure relations. - std::vector<double> turbParam(8, 0.); - bl->closSolver->turbulentClosures(turbParam, u[0], u[1], u[4], bl->Ret[iPoint], bl->Me[iPoint], bl->name); - bl->Hstar[iPoint] = turbParam[0]; - bl->Hstar2[iPoint] = turbParam[1]; - bl->Hk[iPoint] = turbParam[2]; - bl->cf[iPoint] = turbParam[3]; - bl->cd[iPoint] = turbParam[4]; - bl->delta[iPoint] = turbParam[5]; - bl->ctEq[iPoint] = turbParam[6]; - bl->us[iPoint] = turbParam[7]; - } - else - { - std::cout << "Wrong regime\n" - << std::endl; - throw; - } + else if (bl->regime[iPoint] == 1) { + // Turbulent closure relations. + std::vector<double> turbParam(8, 0.); + bl->closSolver->turbulentClosures( + turbParam, u[0], u[1], u[4], bl->Ret[iPoint], bl->Me[iPoint], bl->name); + bl->Hstar[iPoint] = turbParam[0]; + bl->Hstar2[iPoint] = turbParam[1]; + bl->Hk[iPoint] = turbParam[2]; + bl->cf[iPoint] = turbParam[3]; + bl->cd[iPoint] = turbParam[4]; + bl->delta[iPoint] = turbParam[5]; + bl->ctEq[iPoint] = turbParam[6]; + bl->us[iPoint] = turbParam[7]; + } else { + std::cout << "Wrong regime\n" << std::endl; + throw; + } - // Gradients computation. - double dx = (bl->loc[iPoint] - bl->loc[iPoint-1]); - double dxExt = (bl->xxExt[iPoint] - bl->xxExt[iPoint-1]); - double dt_dx = (u[0] - bl->u[(iPoint - 1) * nVar + 0]) / dx; - double dH_dx = (u[1] - bl->u[(iPoint - 1) * nVar + 1]) / dx; - double due_dx = (u[3] - bl->u[(iPoint - 1) * nVar + 3]) / dx; - double dct_dx = (u[4] - bl->u[(iPoint - 1) * nVar + 4]) / dx; - double dHstar_dx = (bl->Hstar[iPoint] - bl->Hstar[iPoint - 1]) / dx; + // Gradients computation. + double dx = (bl->loc[iPoint] - bl->loc[iPoint - 1]); + double dxExt = (bl->xxExt[iPoint] - bl->xxExt[iPoint - 1]); + double dt_dx = (u[0] - bl->u[(iPoint - 1) * nVar + 0]) / dx; + double dH_dx = (u[1] - bl->u[(iPoint - 1) * nVar + 1]) / dx; + double due_dx = (u[3] - bl->u[(iPoint - 1) * nVar + 3]) / dx; + double dct_dx = (u[4] - bl->u[(iPoint - 1) * nVar + 4]) / dx; + double dHstar_dx = (bl->Hstar[iPoint] - bl->Hstar[iPoint - 1]) / dx; - double dueExt_dx = (bl->vt[iPoint] - bl->vt[iPoint-1]) / dxExt; - double ddeltaStarExt_dx = (bl->deltaStarExt[iPoint] - bl->deltaStarExt[iPoint-1]) / dxExt; + double dueExt_dx = (bl->vt[iPoint] - bl->vt[iPoint - 1]) / dxExt; + double ddeltaStarExt_dx = + (bl->deltaStarExt[iPoint] - bl->deltaStarExt[iPoint - 1]) / dxExt; - double c = 4 / (M_PI * dx); - double cExt = 4 / (M_PI * dxExt); + double c = 4 / (M_PI * dx); + double cExt = 4 / (M_PI * dxExt); - // Amplification routine. - double dN_dx = 0.0; - double ax = 0.0; - if (bl->xtrF == -1.0 && bl->regime[iPoint] == 0) - { - // No forced transition and laminar regime. - ax = amplificationRoutine(bl->Hk[iPoint], bl->Ret[iPoint], u[0]); - dN_dx = (u[2] - bl->u[(iPoint - 1) * nVar + 2]) / dx; - } + // Amplification routine. + double dN_dx = 0.0; + double ax = 0.0; + if (bl->xtrF == -1.0 && bl->regime[iPoint] == 0) { + // No forced transition and laminar regime. + ax = amplificationRoutine(bl->Hk[iPoint], bl->Ret[iPoint], u[0]); + dN_dx = (u[2] - bl->u[(iPoint - 1) * nVar + 2]) / dx; + } - double Mea = bl->Me[iPoint]; - double Hstara = bl->Hstar[iPoint]; - double Hstar2a = bl->Hstar2[iPoint]; - double Hka = bl->Hk[iPoint]; - double cfa = bl->cf[iPoint]; - double cda = bl->cd[iPoint]; - double deltaa = bl->delta[iPoint]; - double ctEqa = bl->ctEq[iPoint]; - double usa = bl->us[iPoint]; + double Mea = bl->Me[iPoint]; + double Hstara = bl->Hstar[iPoint]; + double Hstar2a = bl->Hstar2[iPoint]; + double Hka = bl->Hk[iPoint]; + double cfa = bl->cf[iPoint]; + double cda = bl->cd[iPoint]; + double deltaa = bl->delta[iPoint]; + double ctEqa = bl->ctEq[iPoint]; + double usa = bl->us[iPoint]; - //--------------------------------------------------------------------------------// - // Integral boundary layer equations. // + //--------------------------------------------------------------------------------// + // Integral boundary layer equations. // - // Space part. - // spaceVector(0) = dt_dx + (2 + u[1] - Mea * Mea) * (u[0] / u[3]) * due_dx - cfa / 2; - // spaceVector(1) = u[0] * dHstar_dx + (2 * Hstar2a + Hstara * (1 - u[1])) * u[0] / u[3] * due_dx - 2 * cda + Hstara * cfa / 2; - // spaceVector(2) = dN_dx - ax; - // spaceVector(3) = due_dx - c * (u[1] * dt_dx + u[0] * dH_dx) - dueExt_dx + cExt * ddeltaStarExt_dx; + // Space part. + // spaceVector(0) = dt_dx + (2 + u[1] - Mea * Mea) * (u[0] / u[3]) * due_dx - + // cfa / 2; spaceVector(1) = u[0] * dHstar_dx + (2 * Hstar2a + Hstara * (1 - + // u[1])) * u[0] / u[3] * due_dx - 2 * cda + Hstara * cfa / 2; spaceVector(2) + // = dN_dx - ax; spaceVector(3) = due_dx - c * (u[1] * dt_dx + u[0] * dH_dx) - + // dueExt_dx + cExt * ddeltaStarExt_dx; - // if (bl->regime[iPoint] == 1) - // spaceVector(4) = (2 * deltaa / u[4]) * dct_dx - 5.6 * (ctEqa - u[4] * dissipRatio) - 2 * deltaa * (4 / (3 * u[1] * u[0]) * (cfa / 2 - (((Hka - 1) / (6.7 * Hka * dissipRatio)) * ((Hka - 1) / (6.7 * Hka * dissipRatio)))) - 1 / u[3] * due_dx); + // if (bl->regime[iPoint] == 1) + // spaceVector(4) = (2 * deltaa / u[4]) * dct_dx - 5.6 * (ctEqa - u[4] * + // dissipRatio) - 2 * deltaa * (4 / (3 * u[1] * u[0]) * (cfa / 2 - (((Hka + // - 1) / (6.7 * Hka * dissipRatio)) * ((Hka - 1) / (6.7 * Hka * + // dissipRatio)))) - 1 / u[3] * due_dx); - // // Time part. - // timeMatrix(0, 0) = u[1] / u[3]; - // timeMatrix(0, 1) = u[0] / u[3]; - // timeMatrix(0, 3) = u[0] * u[1] / (u[3] * u[3]); + // // Time part. + // timeMatrix(0, 0) = u[1] / u[3]; + // timeMatrix(0, 1) = u[0] / u[3]; + // timeMatrix(0, 3) = u[0] * u[1] / (u[3] * u[3]); - // timeMatrix(1, 0) = (1 + u[1] * (1 - Hstara)) / u[3]; - // timeMatrix(1, 1) = (1 - Hstara) * u[0] / u[3]; - // timeMatrix(1, 3) = (2 - Hstara * u[1]) * u[0] / (u[3] * u[3]); + // timeMatrix(1, 0) = (1 + u[1] * (1 - Hstara)) / u[3]; + // timeMatrix(1, 1) = (1 - Hstara) * u[0] / u[3]; + // timeMatrix(1, 3) = (2 - Hstara * u[1]) * u[0] / (u[3] * u[3]); - // timeMatrix(2, 2) = 1.; + // timeMatrix(2, 2) = 1.; - // timeMatrix(3, 0) = -c * u[1]; - // timeMatrix(3, 1) = -c * u[0]; - // timeMatrix(3, 3) = 1.; + // timeMatrix(3, 0) = -c * u[1]; + // timeMatrix(3, 1) = -c * u[0]; + // timeMatrix(3, 3) = 1.; - // if (bl->regime[iPoint] == 1) - // { - // timeMatrix(4, 3) = 2 * deltaa / (usa * u[3] * u[3]); - // timeMatrix(4, 4) = 2 * deltaa / (u[3] * u[4] * usa); - // } - // else - // timeMatrix(4, 4) = 1.0; - //--------------------------------------------------------------------------------// + // if (bl->regime[iPoint] == 1) + // { + // timeMatrix(4, 3) = 2 * deltaa / (usa * u[3] * u[3]); + // timeMatrix(4, 4) = 2 * deltaa / (u[3] * u[4] * usa); + // } + // else + // timeMatrix(4, 4) = 1.0; + //--------------------------------------------------------------------------------// - VectorXd result = VectorXd::Zero(5); + VectorXd result = VectorXd::Zero(5); - if (bl->regime[iPoint] == 0) - { - result[0] = 0.5*(-2.0*u[0]*(1.0*u[1] - 2.0)*(c*(dH_dx*u[0] + dt_dx*u[1]) - cExt*ddeltaStarExt_dx + dueExt_dx - due_dx) + 1.0*(c*u[0]*u[1] + u[3])*(2.0*due_dx*u[0]*(2.*Hstar2a - Hstara*(u[1] - 1)) + 1.0*u[3]*(Hstara*cfa - 4*cda + 2.*dHstar_dx*u[0])) + 1.0*(2.*due_dx*u[0]*(-Mea*Mea + u[1] + 2) + u[3]*(-cfa + 2.*dt_dx))*(1.0*Hstara*c*u[0]*u[1] + 1.0*Hstara*u[3] - 2.0*c*u[0] - 1.0*u[3]))/(c*u[0]*u[1] + u[3]); - result[1] = 0.5*(2.0*u[0]*u[1]*(u[1] - 1)*(c*(dH_dx*u[0] + dt_dx*u[1]) - cExt*ddeltaStarExt_dx + dueExt_dx - due_dx) - 1.0*u[1]*(c*u[0]*u[1] + u[3])*(2.*due_dx*u[0]*(2.*Hstar2a - Hstara*(u[1] - 1)) + u[3]*(Hstara*cfa - 4*cda + 2.*dHstar_dx*u[0])) + 1.0*(2.*due_dx*u[0]*(-Mea*Mea + u[1] + 2) + u[3]*(-cfa + 2.*dt_dx))*(-1.0*Hstara*c*u[0]*u[1]*u[1] - 1.0*Hstara*u[1]*u[3] + 2.0*c*u[0]*u[1] + 1.0*u[1]*u[3] + 1.0*u[3]))/(u[0]*(c*u[0]*u[1] + u[3])); - result[2] = -1.0*ax + 1.0*dN_dx; - result[3] = 1.0*u[3]*(-1.0*c*(dH_dx*u[0] + dt_dx*u[1]) + 0.5*c*(2.*due_dx*u[0]*(-Mea*Mea + u[1] + 2) + u[3]*(-cfa + 2.*dt_dx)) + 1.0*cExt*ddeltaStarExt_dx - 1.0*dueExt_dx + 1.0*due_dx)/(c*u[0]*u[1] + u[3]); - result[4] = 0.; - } - else if (bl->regime[iPoint] == 1) - { - result[0] = (-u[0]*(u[1] - 2)*(c*(dH_dx*u[0] + dt_dx*u[1]) - cExt*ddeltaStarExt_dx + dueExt_dx - due_dx) + (c*u[0]*u[1] + u[3])*(2.*due_dx*u[0]*(2.*Hstar2a - Hstara*(u[1] - 1)) + u[3]*(Hstara*cfa - 4*cda + 2.*dHstar_dx*u[0]))/2. + (2.*due_dx*u[0]*(-Mea*Mea + u[1] + 2) + u[3]*(-cfa + 2.*dt_dx))*(Hstara*c*u[0]*u[1] + Hstara*u[3] - 2.*c*u[0] - u[3])/2.)/(c*u[0]*u[1] + u[3]); - result[1] = (2.*u[0]*u[1]*(u[1] - 1)*(c*(dH_dx*u[0] + dt_dx*u[1]) - cExt*ddeltaStarExt_dx + dueExt_dx - due_dx) - u[1]*(c*u[0]*u[1] + u[3])*(2.*due_dx*u[0]*(2.*Hstar2a - Hstara*(u[1] - 1)) + u[3]*(Hstara*cfa - 4*cda + 2.*dHstar_dx*u[0])) + (2.*due_dx*u[0]*(-Mea*Mea + u[1] + 2) + u[3]*(-cfa + 2.*dt_dx))*(-Hstara*c*u[0]*u[1]*u[1] - Hstara*u[1]*u[3] + 2.*c*u[0]*u[1] + u[1]*u[3] + u[3]))/(2.*u[0]*(c*u[0]*u[1] + u[3])); - result[2] = -ax + dN_dx; - result[3] = u[3]*(-2.*c*(dH_dx*u[0] + dt_dx*u[1]) + c*(2.*due_dx*u[0]*(-Mea*Mea + u[1] + 2) + u[3]*(-cfa + 2.*dt_dx)) + 2.*cExt*ddeltaStarExt_dx - 2.*dueExt_dx + 2.*due_dx)/(2.*(c*u[0]*u[1] + u[3])); - result[4] = (-Hka*Hka*c*deltaa*dissipRatio*dissipRatio*u[0]*u[1]*u[4]*(2.*due_dx*u[0]*(-Mea*Mea + u[1] + 2) + u[3]*(-cfa + 2.*dt_dx))/2. + Hka*Hka*deltaa*dissipRatio*dissipRatio*u[0]*u[1]*u[4]*(c*(dH_dx*u[0] + dt_dx*u[1]) - cExt*ddeltaStarExt_dx + dueExt_dx - due_dx) + usa*(c*u[0]*u[1] + u[3])*(6*Hka*Hka*dct_dx*deltaa*dissipRatio*dissipRatio*u[0]*u[1]*u[3] + 16.8*Hka*Hka*dissipRatio*dissipRatio*u[0]*u[1]*u[3]*u[4]*(-ctEqa + dissipRatio*u[4]) + 2.*deltaa*u[4]*(3*Hka*Hka*dissipRatio*dissipRatio*due_dx*u[0]*u[1] + u[3]*(-2.*Hka*Hka*cfa*dissipRatio*dissipRatio + 0.0891067052795723*(Hka - 1)*(Hka - 1))))/6)/(Hka*Hka*deltaa*dissipRatio*dissipRatio*u[0]*u[1]*(c*u[0]*u[1] + u[3])); - } + if (bl->regime[iPoint] == 0) { + result[0] = + 0.5 * + (-2.0 * u[0] * (1.0 * u[1] - 2.0) * + (c * (dH_dx * u[0] + dt_dx * u[1]) - cExt * ddeltaStarExt_dx + + dueExt_dx - due_dx) + + 1.0 * (c * u[0] * u[1] + u[3]) * + (2.0 * due_dx * u[0] * (2. * Hstar2a - Hstara * (u[1] - 1)) + + 1.0 * u[3] * (Hstara * cfa - 4 * cda + 2. * dHstar_dx * u[0])) + + 1.0 * + (2. * due_dx * u[0] * (-Mea * Mea + u[1] + 2) + + u[3] * (-cfa + 2. * dt_dx)) * + (1.0 * Hstara * c * u[0] * u[1] + 1.0 * Hstara * u[3] - + 2.0 * c * u[0] - 1.0 * u[3])) / + (c * u[0] * u[1] + u[3]); + result[1] = + 0.5 * + (2.0 * u[0] * u[1] * (u[1] - 1) * + (c * (dH_dx * u[0] + dt_dx * u[1]) - cExt * ddeltaStarExt_dx + + dueExt_dx - due_dx) - + 1.0 * u[1] * (c * u[0] * u[1] + u[3]) * + (2. * due_dx * u[0] * (2. * Hstar2a - Hstara * (u[1] - 1)) + + u[3] * (Hstara * cfa - 4 * cda + 2. * dHstar_dx * u[0])) + + 1.0 * + (2. * due_dx * u[0] * (-Mea * Mea + u[1] + 2) + + u[3] * (-cfa + 2. * dt_dx)) * + (-1.0 * Hstara * c * u[0] * u[1] * u[1] - + 1.0 * Hstara * u[1] * u[3] + 2.0 * c * u[0] * u[1] + + 1.0 * u[1] * u[3] + 1.0 * u[3])) / + (u[0] * (c * u[0] * u[1] + u[3])); + result[2] = -1.0 * ax + 1.0 * dN_dx; + result[3] = + 1.0 * u[3] * + (-1.0 * c * (dH_dx * u[0] + dt_dx * u[1]) + + 0.5 * c * + (2. * due_dx * u[0] * (-Mea * Mea + u[1] + 2) + + u[3] * (-cfa + 2. * dt_dx)) + + 1.0 * cExt * ddeltaStarExt_dx - 1.0 * dueExt_dx + 1.0 * due_dx) / + (c * u[0] * u[1] + u[3]); + result[4] = 0.; + } else if (bl->regime[iPoint] == 1) { + result[0] = + (-u[0] * (u[1] - 2) * + (c * (dH_dx * u[0] + dt_dx * u[1]) - cExt * ddeltaStarExt_dx + + dueExt_dx - due_dx) + + (c * u[0] * u[1] + u[3]) * + (2. * due_dx * u[0] * (2. * Hstar2a - Hstara * (u[1] - 1)) + + u[3] * (Hstara * cfa - 4 * cda + 2. * dHstar_dx * u[0])) / + 2. + + (2. * due_dx * u[0] * (-Mea * Mea + u[1] + 2) + + u[3] * (-cfa + 2. * dt_dx)) * + (Hstara * c * u[0] * u[1] + Hstara * u[3] - 2. * c * u[0] - u[3]) / + 2.) / + (c * u[0] * u[1] + u[3]); + result[1] = + (2. * u[0] * u[1] * (u[1] - 1) * + (c * (dH_dx * u[0] + dt_dx * u[1]) - cExt * ddeltaStarExt_dx + + dueExt_dx - due_dx) - + u[1] * (c * u[0] * u[1] + u[3]) * + (2. * due_dx * u[0] * (2. * Hstar2a - Hstara * (u[1] - 1)) + + u[3] * (Hstara * cfa - 4 * cda + 2. * dHstar_dx * u[0])) + + (2. * due_dx * u[0] * (-Mea * Mea + u[1] + 2) + + u[3] * (-cfa + 2. * dt_dx)) * + (-Hstara * c * u[0] * u[1] * u[1] - Hstara * u[1] * u[3] + + 2. * c * u[0] * u[1] + u[1] * u[3] + u[3])) / + (2. * u[0] * (c * u[0] * u[1] + u[3])); + result[2] = -ax + dN_dx; + result[3] = u[3] * + (-2. * c * (dH_dx * u[0] + dt_dx * u[1]) + + c * (2. * due_dx * u[0] * (-Mea * Mea + u[1] + 2) + + u[3] * (-cfa + 2. * dt_dx)) + + 2. * cExt * ddeltaStarExt_dx - 2. * dueExt_dx + 2. * due_dx) / + (2. * (c * u[0] * u[1] + u[3])); + result[4] = + (-Hka * Hka * c * deltaa * dissipRatio * dissipRatio * u[0] * u[1] * + u[4] * + (2. * due_dx * u[0] * (-Mea * Mea + u[1] + 2) + + u[3] * (-cfa + 2. * dt_dx)) / + 2. + + Hka * Hka * deltaa * dissipRatio * dissipRatio * u[0] * u[1] * u[4] * + (c * (dH_dx * u[0] + dt_dx * u[1]) - cExt * ddeltaStarExt_dx + + dueExt_dx - due_dx) + + usa * (c * u[0] * u[1] + u[3]) * + (6 * Hka * Hka * dct_dx * deltaa * dissipRatio * dissipRatio * + u[0] * u[1] * u[3] + + 16.8 * Hka * Hka * dissipRatio * dissipRatio * u[0] * u[1] * + u[3] * u[4] * (-ctEqa + dissipRatio * u[4]) + + 2. * deltaa * u[4] * + (3 * Hka * Hka * dissipRatio * dissipRatio * due_dx * u[0] * + u[1] + + u[3] * (-2. * Hka * Hka * cfa * dissipRatio * dissipRatio + + 0.0891067052795723 * (Hka - 1) * (Hka - 1)))) / + 6) / + (Hka * Hka * deltaa * dissipRatio * dissipRatio * u[0] * u[1] * + (c * u[0] * u[1] + u[3])); + } - return result; + return result; } /** @@ -209,55 +289,56 @@ VectorXd Fluxes::blLaws(size_t iPoint, BoundaryLayer *bl, std::vector<double> u) * @param theta Momentum thickness. * @return double */ -double Fluxes::amplificationRoutine(double Hk, double Ret, double theta) const -{ - double dgr = 0.08; - double Hk1 = 3.5; - double Hk2 = 4.; - double Hmi = (1 / (Hk - 1)); - double logRet_crit = 2.492 * std::pow(1 / (Hk - 1.), 0.43) + 0.7 * (std::tanh(14 * Hmi - 9.24) + 1.0); // value at which the amplification starts to grow +double Fluxes::amplificationRoutine(double Hk, double Ret, double theta) const { + double dgr = 0.08; + double Hk1 = 3.5; + double Hk2 = 4.; + double Hmi = (1 / (Hk - 1)); + double logRet_crit = + 2.492 * std::pow(1 / (Hk - 1.), 0.43) + + 0.7 * (std::tanh(14 * Hmi - 9.24) + + 1.0); // value at which the amplification starts to grow - double ax = 0.; - if (Ret <= 0.) - Ret = 1.; - if (std::log10(Ret) < logRet_crit - dgr) - ax = 0.; + double ax = 0.; + if (Ret <= 0.) + Ret = 1.; + if (std::log10(Ret) < logRet_crit - dgr) + ax = 0.; + else { + double rNorm = (std::log10(Ret) - (logRet_crit - dgr)) / (2 * dgr); + double Rfac = 0.; + if (rNorm <= 0) + Rfac = 0.; + if (rNorm >= 1) + Rfac = 1.; else - { - double rNorm = (std::log10(Ret) - (logRet_crit - dgr)) / (2 * dgr); - double Rfac = 0.; - if (rNorm <= 0) - Rfac = 0.; - if (rNorm >= 1) - Rfac = 1.; - else - Rfac = 3 * rNorm * rNorm - 2 * rNorm * rNorm * rNorm; + Rfac = 3 * rNorm * rNorm - 2 * rNorm * rNorm * rNorm; - // Normal envelope amplification rate - double m = -0.05 + 2.7 * Hmi - 5.5 * Hmi * Hmi + 3 * Hmi * Hmi * Hmi + 0.1 * std::exp(-20 * Hmi); - double arg = 3.87 * Hmi - 2.52; - double dndRet = 0.028 * (Hk - 1) - 0.0345 * std::exp(-(arg * arg)); - ax = (m * dndRet / theta) * Rfac; + // Normal envelope amplification rate + double m = -0.05 + 2.7 * Hmi - 5.5 * Hmi * Hmi + 3 * Hmi * Hmi * Hmi + + 0.1 * std::exp(-20 * Hmi); + double arg = 3.87 * Hmi - 2.52; + double dndRet = 0.028 * (Hk - 1) - 0.0345 * std::exp(-(arg * arg)); + ax = (m * dndRet / theta) * Rfac; - // Set correction for separated profiles - if (Hk > Hk1) - { - double Hnorm = (Hk - Hk1) / (Hk2 - Hk1); - double Hfac = 0.; - if (Hnorm >= 1) - Hfac = 1.; - else - Hfac = 3 * Hnorm * Hnorm - 2 * Hnorm * Hnorm * Hnorm; - double ax1 = ax; - double gro = 0.3 + 0.35 * std::exp(-0.15 * (Hk - 5)); - double tnr = std::tanh(1.2 * (std::log10(Ret) - gro)); - double ax2 = (0.086 * tnr - 0.25 / std::pow((Hk - 1), 1.5)) / theta; - if (ax2 < 0.) - ax2 = 0.; - ax = Hfac * ax2 + (1 - Hfac) * ax1; - if (ax < 0.) - ax = 0.; - } + // Set correction for separated profiles + if (Hk > Hk1) { + double Hnorm = (Hk - Hk1) / (Hk2 - Hk1); + double Hfac = 0.; + if (Hnorm >= 1) + Hfac = 1.; + else + Hfac = 3 * Hnorm * Hnorm - 2 * Hnorm * Hnorm * Hnorm; + double ax1 = ax; + double gro = 0.3 + 0.35 * std::exp(-0.15 * (Hk - 5)); + double tnr = std::tanh(1.2 * (std::log10(Ret) - gro)); + double ax2 = (0.086 * tnr - 0.25 / std::pow((Hk - 1), 1.5)) / theta; + if (ax2 < 0.) + ax2 = 0.; + ax = Hfac * ax2 + (1 - Hfac) * ax1; + if (ax < 0.) + ax = 0.; } - return ax; + } + return ax; } \ No newline at end of file diff --git a/blast/src/DFluxes.h b/blast/src/DFluxes.h index 7d88b21..c3f1fad 100644 --- a/blast/src/DFluxes.h +++ b/blast/src/DFluxes.h @@ -1,31 +1,32 @@ #ifndef DFLUXES_H #define DFLUXES_H -#include "blast.h" #include "DBoundaryLayer.h" +#include "blast.h" #include <Eigen/Dense> -namespace blast -{ +namespace blast { /** - * @brief Residual and Jacobian computation of the unsteady integral boundary layer equations. + * @brief Residual and Jacobian computation of the unsteady integral boundary + * layer equations. * @author Paul Dechamps */ -class BLAST_API Fluxes -{ +class BLAST_API Fluxes { public: - double Re; ///< Freestream Reynolds number. + double Re; ///< Freestream Reynolds number. public: - Fluxes(double _Re) : Re(_Re){}; - ~Fluxes(){}; - Eigen::VectorXd computeResiduals(size_t iPoint, BoundaryLayer *bl); - Eigen::MatrixXd computeJacobian(size_t iPoint, BoundaryLayer *bl, Eigen::VectorXd const &sysRes, double eps); + Fluxes(double _Re) : Re(_Re){}; + ~Fluxes(){}; + Eigen::VectorXd computeResiduals(size_t iPoint, BoundaryLayer *bl); + Eigen::MatrixXd computeJacobian(size_t iPoint, BoundaryLayer *bl, + Eigen::VectorXd const &sysRes, double eps); private: - Eigen::VectorXd blLaws(size_t iPoint, BoundaryLayer *bl, std::vector<double> u); - double amplificationRoutine(double Hk, double Ret, double theta) const; + Eigen::VectorXd blLaws(size_t iPoint, BoundaryLayer *bl, + std::vector<double> u); + double amplificationRoutine(double Hk, double Ret, double theta) const; }; } // namespace blast #endif // DFLUXES_H diff --git a/blast/src/DSolver.cpp b/blast/src/DSolver.cpp index f111ff2..6c7b39a 100644 --- a/blast/src/DSolver.cpp +++ b/blast/src/DSolver.cpp @@ -16,26 +16,26 @@ using namespace blast; * @param Re Freestream Reynolds number. * @param _maxIt Maximum number of iterations. * @param _tol Convergence tolerance. - * @param _itFrozenJac Number of iterations between which the Jacobian is frozen. + * @param _itFrozenJac Number of iterations between which the Jacobian is + * frozen. */ -Solver::Solver(double _CFL0, double _Minf, double Re, unsigned int _maxIt, double _tol, unsigned int _itFrozenJac) -{ - CFL0 = _CFL0; - maxIt = _maxIt; - tol = _tol; - itFrozenJac0 = _itFrozenJac; - Minf = std::max(_Minf, 0.1); - sysMatrix = new Fluxes(Re); +Solver::Solver(double _CFL0, double _Minf, double Re, unsigned int _maxIt, + double _tol, unsigned int _itFrozenJac) { + CFL0 = _CFL0; + maxIt = _maxIt; + tol = _tol; + itFrozenJac0 = _itFrozenJac; + Minf = std::max(_Minf, 0.1); + sysMatrix = new Fluxes(Re); } /** * @brief Destroy the Time Solver:: Time Solver object. * */ -Solver::~Solver() -{ - delete sysMatrix; - std::cout << "~blast::Solver()\n"; +Solver::~Solver() { + delete sysMatrix; + std::cout << "~blast::Solver()\n"; } /** @@ -44,25 +44,24 @@ Solver::~Solver() * @param iPoint Marker id. * @param bl Boundary layer region. */ -void Solver::initialCondition(size_t iPoint, BoundaryLayer *bl) -{ - size_t nVar = bl->getnVar(); - for (size_t k = 0; k < nVar; ++k) - bl->u[iPoint * nVar + k] = bl->u[(iPoint - 1) * nVar + k]; - bl->u[iPoint * nVar + 3] = bl->vt[iPoint]; - - bl->Ret[iPoint] = bl->Ret[iPoint - 1]; - bl->cd[iPoint] = bl->cd[iPoint - 1]; - bl->cf[iPoint] = bl->cf[iPoint - 1]; - bl->Hstar[iPoint] = bl->Hstar[iPoint - 1]; - bl->Hstar2[iPoint] = bl->Hstar2[iPoint - 1]; - bl->Hk[iPoint] = bl->Hk[iPoint - 1]; - bl->ctEq[iPoint] = bl->ctEq[iPoint - 1]; - bl->us[iPoint] = bl->us[iPoint - 1]; - bl->delta[iPoint] = bl->delta[iPoint - 1]; - bl->deltaStar[iPoint] = bl->deltaStar[iPoint - 1]; - if (bl->regime[iPoint] == 1 && bl->u[iPoint * nVar + 4] <= 0) - bl->u[iPoint * nVar + 4] = 0.03; +void Solver::initialCondition(size_t iPoint, BoundaryLayer *bl) { + size_t nVar = bl->getnVar(); + for (size_t k = 0; k < nVar; ++k) + bl->u[iPoint * nVar + k] = bl->u[(iPoint - 1) * nVar + k]; + bl->u[iPoint * nVar + 3] = bl->vt[iPoint]; + + bl->Ret[iPoint] = bl->Ret[iPoint - 1]; + bl->cd[iPoint] = bl->cd[iPoint - 1]; + bl->cf[iPoint] = bl->cf[iPoint - 1]; + bl->Hstar[iPoint] = bl->Hstar[iPoint - 1]; + bl->Hstar2[iPoint] = bl->Hstar2[iPoint - 1]; + bl->Hk[iPoint] = bl->Hk[iPoint - 1]; + bl->ctEq[iPoint] = bl->ctEq[iPoint - 1]; + bl->us[iPoint] = bl->us[iPoint - 1]; + bl->delta[iPoint] = bl->delta[iPoint - 1]; + bl->deltaStar[iPoint] = bl->deltaStar[iPoint - 1]; + if (bl->regime[iPoint] == 1 && bl->u[iPoint * nVar + 4] <= 0) + bl->u[iPoint * nVar + 4] = 0.03; } /** @@ -72,70 +71,67 @@ void Solver::initialCondition(size_t iPoint, BoundaryLayer *bl) * @param bl Boundary layer region. * @return int */ -int Solver::integration(size_t iPoint, BoundaryLayer *bl) -{ - size_t nVar = bl->getnVar(); - - // Save initial condition. - std::vector<double> sln0(nVar, 0.); - for (size_t i = 0; i < nVar; ++i) - sln0[i] = bl->u[iPoint * nVar + i]; - - // Initialize time integration variables. - double dx = bl->loc[iPoint] - bl->loc[iPoint-1]; - - // Initial time step. - double CFL = CFL0; - unsigned int itFrozenJac = itFrozenJac0; - double timeStep = setTimeStep(CFL, dx, bl->vt[iPoint]); - MatrixXd IMatrix(5, 5); - IMatrix = MatrixXd::Identity(5, 5) / timeStep; +int Solver::integration(size_t iPoint, BoundaryLayer *bl) { + size_t nVar = bl->getnVar(); + + // Save initial condition. + std::vector<double> sln0(nVar, 0.); + for (size_t i = 0; i < nVar; ++i) + sln0[i] = bl->u[iPoint * nVar + i]; + + // Initialize time integration variables. + double dx = bl->loc[iPoint] - bl->loc[iPoint - 1]; + + // Initial time step. + double CFL = CFL0; + unsigned int itFrozenJac = itFrozenJac0; + double timeStep = setTimeStep(CFL, dx, bl->vt[iPoint]); + MatrixXd IMatrix(5, 5); + IMatrix = MatrixXd::Identity(5, 5) / timeStep; - // Initial system residuals. - VectorXd sysRes = sysMatrix->computeResiduals(iPoint, bl); - double normSysRes0 = sysRes.norm(); - double normSysRes = normSysRes0; + // Initial system residuals. + VectorXd sysRes = sysMatrix->computeResiduals(iPoint, bl); + double normSysRes0 = sysRes.norm(); + double normSysRes = normSysRes0; - MatrixXd JacMatrix = MatrixXd::Zero(5, 5); - VectorXd slnIncr = VectorXd::Zero(5); + MatrixXd JacMatrix = MatrixXd::Zero(5, 5); + VectorXd slnIncr = VectorXd::Zero(5); - unsigned int innerIters = 0; // Inner (non-linear) iterations + unsigned int innerIters = 0; // Inner (non-linear) iterations - while (innerIters < maxIt) - { - // Jacobian computation. - if (innerIters % itFrozenJac == 0) - JacMatrix = sysMatrix->computeJacobian(iPoint, bl, sysRes, 1e-8); + while (innerIters < maxIt) { + // Jacobian computation. + if (innerIters % itFrozenJac == 0) + JacMatrix = sysMatrix->computeJacobian(iPoint, bl, sysRes, 1e-8); - // Linear system. - slnIncr = (JacMatrix + IMatrix).partialPivLu().solve(-sysRes); + // Linear system. + slnIncr = (JacMatrix + IMatrix).partialPivLu().solve(-sysRes); - // Solution increment. - for (size_t k = 0; k < nVar; ++k) - bl->u[iPoint * nVar + k] += slnIncr(k); - bl->u[iPoint * nVar + 0] = std::max(bl->u[iPoint * nVar + 0], 1e-6); - bl->u[iPoint * nVar + 1] = std::max(bl->u[iPoint * nVar + 1], 1.0005); + // Solution increment. + for (size_t k = 0; k < nVar; ++k) + bl->u[iPoint * nVar + k] += slnIncr(k); + bl->u[iPoint * nVar + 0] = std::max(bl->u[iPoint * nVar + 0], 1e-6); + bl->u[iPoint * nVar + 1] = std::max(bl->u[iPoint * nVar + 1], 1.0005); - sysRes = sysMatrix->computeResiduals(iPoint, bl); - normSysRes = (sysRes + slnIncr / timeStep).norm(); + sysRes = sysMatrix->computeResiduals(iPoint, bl); + normSysRes = (sysRes + slnIncr / timeStep).norm(); - if (normSysRes <= tol * normSysRes0) - return 0; // Successfull exit. + if (normSysRes <= tol * normSysRes0) + return 0; // Successfull exit. - // CFL adaptation. - CFL = std::max(CFL0 * pow(normSysRes0 / normSysRes, 0.7), 0.1); - timeStep = setTimeStep(CFL, dx, bl->vt[iPoint]); - IMatrix = MatrixXd::Identity(5, 5) / timeStep; + // CFL adaptation. + CFL = std::max(CFL0 * pow(normSysRes0 / normSysRes, 0.7), 0.1); + timeStep = setTimeStep(CFL, dx, bl->vt[iPoint]); + IMatrix = MatrixXd::Identity(5, 5) / timeStep; - innerIters++; - } + innerIters++; + } - if (std::isnan(normSysRes) || normSysRes / normSysRes0 > 1e-3) - { - resetSolution(iPoint, bl, sln0); - return -1; - } - return innerIters; + if (std::isnan(normSysRes) || normSysRes / normSysRes0 > 1e-3) { + resetSolution(iPoint, bl, sln0); + return -1; + } + return innerIters; } /** @@ -146,17 +142,16 @@ int Solver::integration(size_t iPoint, BoundaryLayer *bl) * @param invVel Inviscid velocity. * @return double */ -double Solver::setTimeStep(double CFL, double dx, double invVel) const -{ - // Speed of sound. - double gradU2 = (invVel * invVel); - double soundSpeed = computeSoundSpeed(gradU2); +double Solver::setTimeStep(double CFL, double dx, double invVel) const { + // Speed of sound. + double gradU2 = (invVel * invVel); + double soundSpeed = computeSoundSpeed(gradU2); - // Velocity of the fastest travelling wave. - double advVel = soundSpeed + invVel; + // Velocity of the fastest travelling wave. + double advVel = soundSpeed + invVel; - // Time step computation. - return CFL * dx / advVel; + // Time step computation. + return CFL * dx / advVel; } /** @@ -165,67 +160,70 @@ double Solver::setTimeStep(double CFL, double dx, double invVel) const * @param gradU2 Inviscid velocity squared in the cell. * @return double */ -double Solver::computeSoundSpeed(double gradU2) const -{ - return sqrt(1 / (Minf * Minf) + 0.5 * (gamma - 1) * (1 - gradU2)); +double Solver::computeSoundSpeed(double gradU2) const { + return sqrt(1 / (Minf * Minf) + 0.5 * (gamma - 1) * (1 - gradU2)); } /** - * @brief Resets the solution of the point wrt its initial condition (sln0) or the previous point. + * @brief Resets the solution of the point wrt its initial condition (sln0) or + * the previous point. * * @param iPoint Marker id. * @param bl Boundary layer region. * @param sln0 Initial solution at the point. * @param usePrevPoint if 1, use the solution at previous point instead of sln0. */ -void Solver::resetSolution(size_t iPoint, BoundaryLayer *bl, std::vector<double> sln0, bool usePrevPoint) -{ - size_t nVar = bl->getnVar(); - - // Reset solution. - if (usePrevPoint) - for (size_t k = 0; k < nVar; ++k) - bl->u[iPoint * nVar + k] = bl->u[(iPoint - 1) * nVar + k]; - else - for (size_t k = 0; k < nVar; ++k) - bl->u[iPoint * nVar + k] = sln0[k]; - - // Reset closures. - bl->Ret[iPoint] = std::max(bl->u[iPoint * nVar + 3] * bl->u[iPoint * nVar + 0] * sysMatrix->Re, 1.0); // Reynolds number based on theta. - bl->deltaStar[iPoint] = bl->u[iPoint * nVar + 0] * bl->u[iPoint * nVar + 1]; // Displacement thickness. - - if (bl->regime[iPoint] == 0) - { - std::vector<double> lamParam(8, 0.); - bl->closSolver->laminarClosures(lamParam, bl->u[iPoint * nVar + 0], bl->u[iPoint * nVar + 1], bl->Ret[iPoint], bl->Me[iPoint], bl->name); - bl->Hstar[iPoint] = lamParam[0]; - bl->Hstar2[iPoint] = lamParam[1]; - bl->Hk[iPoint] = lamParam[2]; - bl->cf[iPoint] = lamParam[3]; - bl->cd[iPoint] = lamParam[4]; - bl->delta[iPoint] = lamParam[5]; - bl->ctEq[iPoint] = lamParam[6]; - bl->us[iPoint] = lamParam[7]; - } - else if (bl->regime[iPoint] == 1) - { - std::vector<double> turbParam(8, 0.); - bl->closSolver->turbulentClosures(turbParam, bl->u[iPoint * nVar + 0], bl->u[iPoint * nVar + 1], bl->u[iPoint * nVar + 4], bl->Ret[iPoint], bl->Me[iPoint], bl->name); - bl->Hstar[iPoint] = turbParam[0]; - bl->Hstar2[iPoint] = turbParam[1]; - bl->Hk[iPoint] = turbParam[2]; - bl->cf[iPoint] = turbParam[3]; - bl->cd[iPoint] = turbParam[4]; - bl->delta[iPoint] = turbParam[5]; - bl->ctEq[iPoint] = turbParam[6]; - bl->us[iPoint] = turbParam[7]; - } +void Solver::resetSolution(size_t iPoint, BoundaryLayer *bl, + std::vector<double> sln0, bool usePrevPoint) { + size_t nVar = bl->getnVar(); + + // Reset solution. + if (usePrevPoint) + for (size_t k = 0; k < nVar; ++k) + bl->u[iPoint * nVar + k] = bl->u[(iPoint - 1) * nVar + k]; + else + for (size_t k = 0; k < nVar; ++k) + bl->u[iPoint * nVar + k] = sln0[k]; + + // Reset closures. + bl->Ret[iPoint] = std::max(bl->u[iPoint * nVar + 3] * + bl->u[iPoint * nVar + 0] * sysMatrix->Re, + 1.0); // Reynolds number based on theta. + bl->deltaStar[iPoint] = bl->u[iPoint * nVar + 0] * + bl->u[iPoint * nVar + 1]; // Displacement thickness. + + if (bl->regime[iPoint] == 0) { + std::vector<double> lamParam(8, 0.); + bl->closSolver->laminarClosures(lamParam, bl->u[iPoint * nVar + 0], + bl->u[iPoint * nVar + 1], bl->Ret[iPoint], + bl->Me[iPoint], bl->name); + bl->Hstar[iPoint] = lamParam[0]; + bl->Hstar2[iPoint] = lamParam[1]; + bl->Hk[iPoint] = lamParam[2]; + bl->cf[iPoint] = lamParam[3]; + bl->cd[iPoint] = lamParam[4]; + bl->delta[iPoint] = lamParam[5]; + bl->ctEq[iPoint] = lamParam[6]; + bl->us[iPoint] = lamParam[7]; + } else if (bl->regime[iPoint] == 1) { + std::vector<double> turbParam(8, 0.); + bl->closSolver->turbulentClosures( + turbParam, bl->u[iPoint * nVar + 0], bl->u[iPoint * nVar + 1], + bl->u[iPoint * nVar + 4], bl->Ret[iPoint], bl->Me[iPoint], bl->name); + bl->Hstar[iPoint] = turbParam[0]; + bl->Hstar2[iPoint] = turbParam[1]; + bl->Hk[iPoint] = turbParam[2]; + bl->cf[iPoint] = turbParam[3]; + bl->cd[iPoint] = turbParam[4]; + bl->delta[iPoint] = turbParam[5]; + bl->ctEq[iPoint] = turbParam[6]; + bl->us[iPoint] = turbParam[7]; + } } -void Solver::setCFL0(double _CFL0) -{ - if (_CFL0 > 0) - CFL0 = _CFL0; - else - throw std::runtime_error("Negative CFL numbers are not allowed.\n"); +void Solver::setCFL0(double _CFL0) { + if (_CFL0 > 0) + CFL0 = _CFL0; + else + throw std::runtime_error("Negative CFL numbers are not allowed.\n"); } \ No newline at end of file diff --git a/blast/src/DSolver.h b/blast/src/DSolver.h index 16c73ba..604c006 100644 --- a/blast/src/DSolver.h +++ b/blast/src/DSolver.h @@ -1,49 +1,52 @@ #ifndef DSOLVER_H #define DSOLVER_H -#include "blast.h" #include "DFluxes.h" +#include "blast.h" -namespace blast -{ +namespace blast { /** * @brief Pseudo-time integration. * @author Paul Dechamps */ -class BLAST_API Solver -{ +class BLAST_API Solver { private: - double CFL0; ///< Initial CFL number. - unsigned int maxIt; ///< Maximum number of iterations. - double tol; ///< Convergence tolerance. - unsigned int itFrozenJac0; ///< Number of iterations between which the Jacobian is frozen. - double const gamma = 1.4; ///< Air heat capacity ratio. - double Minf; ///< Freestream Mach number. + double CFL0; ///< Initial CFL number. + unsigned int maxIt; ///< Maximum number of iterations. + double tol; ///< Convergence tolerance. + unsigned int itFrozenJac0; ///< Number of iterations between which the + ///< Jacobian is frozen. + double const gamma = 1.4; ///< Air heat capacity ratio. + double Minf; ///< Freestream Mach number. - Fluxes *sysMatrix; + Fluxes *sysMatrix; public: - Solver(double _CFL0, double _Minf, double Re, unsigned int _maxIt = 100, double _tol = 1e-8, unsigned int _itFrozenJac = 1); - ~Solver(); - void initialCondition(size_t iPoint, BoundaryLayer *bl); - int integration(size_t iPoint, BoundaryLayer *bl); - - // Getters. - double getCFL0() const { return CFL0; }; - unsigned int getmaxIt() const { return maxIt; }; - unsigned int getitFrozenJac() const { return itFrozenJac0; }; - - // Setters. - void setCFL0(double _CFL0); - void setmaxIt(unsigned int _maxIt) { maxIt = _maxIt; }; - void setitFrozenJac(unsigned int _itFrozenJac) { itFrozenJac0 = _itFrozenJac; }; + Solver(double _CFL0, double _Minf, double Re, unsigned int _maxIt = 100, + double _tol = 1e-8, unsigned int _itFrozenJac = 1); + ~Solver(); + void initialCondition(size_t iPoint, BoundaryLayer *bl); + int integration(size_t iPoint, BoundaryLayer *bl); + + // Getters. + double getCFL0() const { return CFL0; }; + unsigned int getmaxIt() const { return maxIt; }; + unsigned int getitFrozenJac() const { return itFrozenJac0; }; + + // Setters. + void setCFL0(double _CFL0); + void setmaxIt(unsigned int _maxIt) { maxIt = _maxIt; }; + void setitFrozenJac(unsigned int _itFrozenJac) { + itFrozenJac0 = _itFrozenJac; + }; private: - double setTimeStep(double CFL, double dx, double invVel) const; - double computeSoundSpeed(double gradU2) const; - void resetSolution(size_t iPoint, BoundaryLayer *bl, std::vector<double> Sln0, bool usePrevPoint = false); + double setTimeStep(double CFL, double dx, double invVel) const; + double computeSoundSpeed(double gradU2) const; + void resetSolution(size_t iPoint, BoundaryLayer *bl, std::vector<double> Sln0, + bool usePrevPoint = false); }; } // namespace blast #endif // DSOLVER_H diff --git a/blast/src/blast.h b/blast/src/blast.h index 0fcf795..9b526a7 100644 --- a/blast/src/blast.h +++ b/blast/src/blast.h @@ -34,8 +34,7 @@ /** * @brief Namespace for blast module */ -namespace blast -{ +namespace blast { // Solvers class Driver; diff --git a/format/format_cf11.py b/format/format_cf11.py new file mode 100755 index 0000000..25a2636 --- /dev/null +++ b/format/format_cf11.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# This script runs "clang-format" recursively on all C/C++ files +# @authors A. Crovato, R. Boman +# Modified by P. Dechamps + +import sys +import os +import fnmatch +import re +import subprocess + + +def all_files(root, + patterns='*', + skips='*.git*;*build*', + single_level=False, + yield_folders=False): + # self.checkPath(root) + patterns = patterns.split(';') + skips = skips.split(';') + for path, subdirs, files in os.walk(root): + if yield_folders: + files.extend(subdirs) + files.sort() + for name in files: + for pattern in patterns: + if fnmatch.fnmatch(name, pattern): + fullname = os.path.join(path, name) + ok = True + for skip in skips: + if fnmatch.fnmatch(os.path.relpath(fullname, start=root), skip): + ok = False + if ok: + yield fullname + break + if single_level: + break + + +def main(): + + # loop over all files and format them + encs = {} + for f in all_files(os.getcwd(), patterns='*.cpp;*.c;*.h;*.hpp'): + # print(f) + cmd = ['clang-format-11', "-style=file", "-i", f] + retcode = subprocess.call(cmd) + if retcode != 0: + print(f'ERROR: retcode = {retcode}') + break + + +if __name__ == "__main__": + # print('running format_code.py...') + main() -- GitLab