diff --git a/dart/_src/dartw.h b/dart/_src/dartw.h index 54d3a31e17266bd06bf7acd18aac25e805049383..5d2bae91d01c90df1fd03e8233753424a8794503 100644 --- a/dart/_src/dartw.h +++ b/dart/_src/dartw.h @@ -26,3 +26,7 @@ #include "wProblem.h" #include "wSolver.h" #include "wWake.h" +#include "wViscSolver.h" +#include "wBLRegion.h" +#include "wTimeSolver.h" +#include "wViscFluxes.h" diff --git a/dart/_src/dartw.i b/dart/_src/dartw.i index e16e83975d1e51bdb49efa367eb14f935deb0e43..b1eba25b6a021bf5d6c1d3a84b4ea45112ff5420 100644 --- a/dart/_src/dartw.i +++ b/dart/_src/dartw.i @@ -58,6 +58,11 @@ threads="1" %shared_ptr(dart::Newton); %shared_ptr(dart::Adjoint); +%include "wViscSolver.h" +%include "wBLRegion.h" +%include "wTimeSolver.h" +%include "wViscFluxes.h" + %include "wFluid.h" %include "wAssign.h" %include "wFreestream.h" diff --git a/dart/default.py b/dart/default.py index 3a03df5626170c58ef3be646579d518954072a69..e12c4ab8c0118f8dfcf4b2061cc41f840f94da4b 100644 --- a/dart/default.py +++ b/dart/default.py @@ -23,6 +23,12 @@ from fwk.wutils import parseargs import dart import tbox +def initBL(Re, Minf, CFL0): + print('Re default.py', Re, Minf, CFL0) + solver = dart.ViscSolver(Re, Minf, CFL0) + print('ok') + return solver + def mesh(dim, file, pars, bnd, wk = 'wake', wktp = None): """Initialize mesh and mesh writer diff --git a/dart/src/dart.h b/dart/src/dart.h index 2afc45904a47f3012a57caf58b553233bfe721cc..72c71064973cf3954e5cdb8e85577529417d6c1b 100644 --- a/dart/src/dart.h +++ b/dart/src/dart.h @@ -64,6 +64,10 @@ class Picard; class Newton; class FpeLSFunction; class Adjoint; +class ViscSolver; +class BLRegion; +class TimeSolver; +class ViscSolver; // General class F0Ps; diff --git a/dart/src/wBLRegion.cpp b/dart/src/wBLRegion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56115e9bc067e56ae18a2a153a11ce26f0c33449 --- /dev/null +++ b/dart/src/wBLRegion.cpp @@ -0,0 +1,168 @@ +#include "wBLRegion.h" +#include <iostream> +#include <vector> +#include <cmath> + +using namespace tbox; +using namespace dart; + + +BLRegion::BLRegion() +{ + std::cout << "Coucou de BLRegion\n" << std::endl; + + +} // end BLRegion + + +BLRegion::~BLRegion() +{ + std::cout << "~BLRegion()\n"; +} // end ~BLRegion + +void BLRegion::SetMesh(std::vector<double> locM, std::vector<double> globM) +{ + LocMarkers=locM; + GlobMarkers=globM; + nMarkers = locM.size(); + + /* Resize all variables */ + + U.resize(nVar * nMarkers); + Ret.resize(nMarkers); + Cd.resize(nMarkers); + Cf.resize(nMarkers); + Hstar.resize(nMarkers); + Hstar2.resize(nMarkers); + Hk.resize(nMarkers); + Cteq.resize(nMarkers); + Us.resize(nMarkers); + DeltaStar.resize(nMarkers); + Delta.resize(nMarkers); + Me.resize(nMarkers); + Rhoe.resize(nMarkers); + VtExt.resize(nMarkers); + DeltaStarExt.resize(nMarkers); + XxExt.resize(nMarkers); + ReExt.resize(nMarkers); + Regime.resize(nMarkers); +} // End SetMesh + +void BLRegion::SetInvBC(std::vector<double> _Ue, + std::vector<double> _Me, + std::vector<double> _Rhoe) +{ + VtExt = _Ue; + Me = _Me; + Rhoe = _Rhoe; +}// End SetInvBC + +void BLRegion::SetStagBC(double Re) +{ + double dv0 = (VtExt[1] - VtExt[0])/(LocMarkers[1] - LocMarkers[0]); + + if (dv0 > 0){ + U[0] = sqrt(0.075/(Re*dv0)); // Theta + } // End if + else{ + U[0] = 1e-6; // Theta + } // end else + U[1] = 2.23; // H + U[2] = 0; // N + U[3] = VtExt[0]; // ue + U[4] = 0; // Ctau + + Ret[0] = U[3]*U[0]*Re; + + if (Ret[0] < 1){ + Ret[0] = 0; + U[3] = Ret[0]/(U[0]*Re); + } // End if + + LaminarClosures(0); +} // End SetStagBC + +unsigned int BLRegion::GetnVar(){return nVar;} +size_t BLRegion::GetnMarkers(){return nMarkers;} +double BLRegion::GetLocMarkers(size_t iPoint){return LocMarkers[iPoint];} +double BLRegion::GetGlobMarkers(size_t iPoint){return GlobMarkers[iPoint];} +double BLRegion::GetVtExt(size_t iPoint){return VtExt[iPoint];} +double BLRegion::GetMe(size_t iPoint){return Me[iPoint];} +double BLRegion::GetRhoe(size_t iPoint){return Rhoe[iPoint];} +double BLRegion::GetXxExt(size_t iPoint){return XxExt[iPoint];} +double BLRegion::GetDeltaStarExt(size_t iPoint){return DeltaStarExt[iPoint];} + +void BLRegion::PrintSolution(size_t iPoint) +{ + std::cout << "Point " << iPoint << std::endl; + std::cout << "Theta " << U[iPoint * nVar + 0] << " \n" << std::endl; + std::cout << "H " << U[iPoint * nVar + 1] << " \n" << std::endl; + std::cout << "N " << U[iPoint * nVar + 2] << " \n" << std::endl; + std::cout << "ue " << U[iPoint * nVar + 3] << " \n" << std::endl; + std::cout << "Ct " << U[iPoint * nVar + 4] << " \n" << std::endl; + } + +void BLRegion::LaminarClosures(size_t iPoint) +{ + double theta = U[iPoint*nVar+0]; + double H = U[iPoint*nVar+1]; + double ret = Ret[iPoint]; + double me = Me[iPoint]; + double hk = (H - 0.29*me*me)/(1+0.113*me*me); // Kinematic shape factor + if(name == "airfoil"){ + hk = std::max(hk, 1.02); + } + else{ + hk = std::max(hk, 1.00005); + } + hk = std::min(hk,6.0); + double hstar2 = (0.064/(hk-0.8)+0.251)*me*me; // Density shape parameter + double delta = std::min((3.15+ H + (1.72/(hk-1)))*theta, 12*theta); + double hks = hk - 4.35; + double hstar; + if(hk <= 4.35){ + double dens = hk + 1; + hstar = 0.0111*hks*hks/dens - 0.0278*hks*hks*hks/dens + 1.528 -0.0002*(hks*hk)*(hks*hk); + } + else if(hk > 4.35){ + hstar = 1.528 + 0.015*hks*hks/hk; + } + hstar = (hstar + 0.028*me*me)/(1+0.014*me*me); // Whitfield's minor additional compressibility correction + + /* Cf */ + + double cf; + if(hk < 5.5){ + double tmp = (5.5-hk)*(5.5-hk)*(5.5-hk) / (hk+1); + cf = (-0.07 + 0.0727*tmp)/ret; + } + else if(hk >= 5.5){ + double tmp = 1 - 1/(hk-4.5); + cf = (-0.07 + 0.015*tmp*tmp) /ret; + } + + /* Cd */ + + double cd; + if(hk < 4){ + cd = ( 0.00205*pow(4.0-hk, 5.5) + 0.207 ) * (hstar/(2*ret)); + } + else if(hk >= 4){ + double hkCd = (hk-4)*(hk-4); + double denCd = 1+0.02*hkCd; + cd = ( -0.0016*hkCd/denCd + 0.207) * (hstar/(2*ret)); + } + if (name == "wake"){ + cd = 2*(1.10*(1.0-1.0/hk)*(1.0-1.0/hk)/hk)* (hstar/(2*ret)); + cf = 0; + } + Cd[iPoint] = cd; + Cf[iPoint] = cf; + Delta[iPoint] = delta; + Hstar[iPoint] = hstar; + Hstar2[iPoint] = hstar2; + Hk[iPoint] = hk; + Cteq[iPoint] = 0; + Us[iPoint] = 0; +} + diff --git a/dart/src/wBLRegion.h b/dart/src/wBLRegion.h new file mode 100644 index 0000000000000000000000000000000000000000..7f0e2ac2e4a8ad6418bbb1f958aba5ebd80bd94c --- /dev/null +++ b/dart/src/wBLRegion.h @@ -0,0 +1,88 @@ +#ifndef WBLREGION_H +#define WBLREGION_H + +#include "dart.h" +#include <vector> +#include <string> + +namespace dart +{ + +class DART_API BLRegion +{ + +private: + + unsigned int nVar = 5; + + /* Mesh parameters */ + + size_t nMarkers; + std::vector<double> GlobMarkers; /* Position of the mesh elements in the global frame of reference */ + std::vector<double> LocMarkers; /* Position of the mesh elements in the local frame of reference */ + + /* External flow variables */ + + std::vector<double> Me; + std::vector<double> Rhoe; + std::vector<double> VtExt; + std::vector<double> DeltaStarExt; + std::vector<double> XxExt; + std::vector<double> ReExt; + + /* Transition related variables */ + + double nCrit; + +public: + + std::string name; + + /* 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; + std::vector<double> Hstar2; + std::vector<double> Hk; + std::vector<double> Cteq; + std::vector<double> Us; + std::vector<double> Delta; + + std::vector<double> DeltaStar; + + /* Transition related variables */ + + std::vector<double> Regime; + + unsigned int transMarker; + double xtrF; + double xtr; + + BLRegion(); + ~BLRegion(); + void SetMesh(std::vector<double> locM, std::vector<double> globM); + void SetInvBC(std::vector<double> _Ue, + std::vector<double> _Me, + std::vector<double> _Rhoe); + + void SetStagBC(double Re); + + unsigned int GetnVar(); + size_t GetnMarkers(); + double GetLocMarkers(size_t iPoint); + double GetGlobMarkers(size_t iPoint); + double GetVtExt(size_t iPoint); + double GetMe(size_t iPoint); + double GetRhoe(size_t iPoint); + double GetXxExt(size_t iPoint); + double GetDeltaStarExt(size_t iPoint); + + void PrintSolution(size_t iPoint); + + void LaminarClosures(size_t iPoint); +}; +} // namespace dart +#endif //WBLREGION_H \ No newline at end of file diff --git a/dart/src/wTimeSolver.cpp b/dart/src/wTimeSolver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47c09d27f7fcddd6a5f894669116d849db06217b --- /dev/null +++ b/dart/src/wTimeSolver.cpp @@ -0,0 +1,150 @@ +#include "wTimeSolver.h" +#include "wBLRegion.h" +#include "wViscFluxes.h" +#include <Eigen/Dense> +#include <iostream> +#include <vector> +#include <cmath> + +using namespace Eigen; +using namespace tbox; +using namespace dart; + + +TimeSolver::TimeSolver(double _CFL0, double _Minf, unsigned long _maxIt, double _tol, unsigned int _itFrozenJac) +{ + std::cout << "Coucou de TimeSolver\n" << std::endl; + + CFL0 = _CFL0; + maxIt = _maxIt; + tol = _tol; + itFrozenJac0 = _itFrozenJac; + Minf = _Minf; + + SysMatrix = new ViscFluxes(); + +} // end TimeSolver + + +TimeSolver::~TimeSolver() +{ + delete SysMatrix; + std::cout << "~TimeSolver()\n"; +} // end ~TimeSolver + +void TimeSolver::InitialCondition(size_t iPoint, BLRegion *bl) +{ + unsigned int nVar = bl->GetnVar(); + if (initSln){ + + bl->U[iPoint * nVar + 0] = bl->U[(iPoint-1) * nVar + 0]; + bl->U[iPoint * nVar + 1] = bl->U[(iPoint-1) * nVar + 1]; + bl->U[iPoint * nVar + 2] = bl->U[(iPoint-1) * nVar + 2]; + bl->U[iPoint * nVar + 3] = bl->GetVtExt(iPoint); + bl->U[iPoint * nVar + 4] = bl->U[(iPoint-1) * nVar + 4]; + + 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; + } // End if +} // End InitialCondition + +int TimeSolver::Integration(size_t iPoint, BLRegion *bl) +{ + + // Save initial condition + + unsigned int nVar = bl->GetnVar(); + + std::vector<double> temp_U; + for (size_t i=0; i<nVar; ++i){ + temp_U.push_back(bl->U[iPoint*nVar+i]); + } // End for + + // Initialize time integration variables + + double dx = bl->GetLocMarkers(iPoint) - bl->GetLocMarkers(iPoint-1); + + double CFL = CFL0; + unsigned int itFrozenJac = itFrozenJac0; + double timeStep = SetTimeStep(CFL, dx, bl->GetVtExt(iPoint)); + + Matrix<double, 5, 5> IMatrix; + IMatrix = Matrix<double, 5, 5>::Identity() / timeStep; + + Vector<double, 5> SysRes = SysMatrix->ComputeFluxes(iPoint, bl); + double normSysRes0 = SysRes.norm(); + double normSysRes; + + Matrix<double, 5, 5> JacMatrix; + Vector<double, 5> slnIncr; + + unsigned int nErrors = 0; // Number of errors encountered + unsigned int innerIters = 0; // Inner (non-linear) iterations + while (innerIters < maxIt){ + + if(innerIters % itFrozenJac){ + JacMatrix = SysMatrix->ComputeJacobian(iPoint, bl, SysRes, 1e-8); + } + + // Ici on peut faire autrement : .asDiagonal() + slnIncr = (JacMatrix + IMatrix).partialPivLu().solve(SysRes); + + for(size_t k=0; k<slnIncr.size(); ++k){ + bl->U[iPoint*nVar+k] += slnIncr(k); + } + + SysRes = SysMatrix->ComputeFluxes(iPoint, bl); + normSysRes = (SysRes + slnIncr/timeStep).norm(); + + // CFL adaptation. + + CFL = CFL0* pow(normSysRes0/normSysRes, 0.7); + + CFL = std::max(CFL, 1.0); + timeStep = SetTimeStep(CFL, dx, bl->GetVtExt(iPoint)); + IMatrix = Matrix<double, 5, 5>::Identity() / timeStep; + + innerIters++; + } // End while + return innerIters; + return 0; +} // End Integration + +double TimeSolver::SetTimeStep(double CFL, double dx, double invVel) +{ + /* Speed of sound. */ + double gradU2 = (invVel*invVel); + double soundSpeed = ComputeSoundSpeed(gradU2); + + /* Velocity of the fastest travelling wave */ + double advVel = soundSpeed + invVel; + + /* Time step computation */ + return CFL*dx/advVel; +} + +double TimeSolver::ComputeSoundSpeed(double gradU2) +{ + return sqrt(1 / (Minf * Minf) + 0.5 * (gamma - 1) * (1 - gradU2)); +} + + +double TimeSolver::GetCFL0(){return CFL0;} +void TimeSolver::SetCFL0(double _CFL0){CFL0 = _CFL0;} +unsigned long TimeSolver::GetmaxIt(){return maxIt;} +void TimeSolver::SetmaxIt(unsigned long _maxIt){maxIt = _maxIt;} +unsigned int TimeSolver::GetitFrozenJac(){return itFrozenJac0;} +void TimeSolver::SetitFrozenJac(unsigned int _itFrozenJac){itFrozenJac0 = _itFrozenJac;} + +void TimeSolver::SetinitSln(bool _initSln){initSln = _initSln;} \ No newline at end of file diff --git a/dart/src/wTimeSolver.h b/dart/src/wTimeSolver.h new file mode 100644 index 0000000000000000000000000000000000000000..b85ac58145e51425189fc0ca6f421c09f2f50cbf --- /dev/null +++ b/dart/src/wTimeSolver.h @@ -0,0 +1,45 @@ +#ifndef WTIMESOLVER_H +#define WTIMESOLVER_H + +#include "dart.h" +#include "wViscFluxes.h" +#include <vector> +#include <string> + +namespace dart +{ + +class DART_API TimeSolver +{ + +private: + + double CFL0; + unsigned long maxIt; + double tol; + unsigned int itFrozenJac0; + bool initSln = true; + double gamma = 1.4; + double Minf; + + ViscFluxes *SysMatrix; + +public: + TimeSolver(double _CFL0, double _Minf, unsigned long _maxIt = 1000, double _tol = 1e-8, unsigned int _itFrozenJac = 5); + ~TimeSolver(); + void InitialCondition(size_t iPoint, BLRegion *bl); + int Integration(size_t iPoint, BLRegion *bl); + double GetCFL0(); + void SetCFL0(double _CFL0); + unsigned long GetmaxIt(); + void SetmaxIt(unsigned long _maxIt); + unsigned int GetitFrozenJac(); + void SetitFrozenJac(unsigned int _itFrozenJac); + void SetinitSln(bool _initSln); + +private: + double SetTimeStep(double CFL, double dx, double invVel); + double ComputeSoundSpeed(double gradU2); +}; +} // namespace dart +#endif //WTimeSolver_H \ No newline at end of file diff --git a/dart/src/wViscFluxes.cpp b/dart/src/wViscFluxes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0374f60d19eea90895555a9e856291bb2f69c4c6 --- /dev/null +++ b/dart/src/wViscFluxes.cpp @@ -0,0 +1,399 @@ +#define _USE_MATH_DEFINES + +#include "wViscFluxes.h" +#include "wBLRegion.h" +#include <iostream> +#include <Eigen/Dense> +#include <cmath> +#include <algorithm> +#include <string> + +using namespace dart; +using namespace Eigen; + + +ViscFluxes::ViscFluxes() +{ + std::cout << "Coucou de ViscFluxes\n" << std::endl; + + +} // end ViscFluxes + + +ViscFluxes::~ViscFluxes() +{ + std::cout << "~ViscFluxes()\n"; +} // end ~ViscFluxes + +Vector<double, 5> ViscFluxes::ComputeFluxes(size_t iPoint, BLRegion *bl) +{ + unsigned int nVar = bl->GetnVar(); + std::vector<double> u; + for (size_t k=0; k<nVar; ++k){ + u.push_back(bl->U[iPoint*nVar + k]); + } // End for + return BLlaws(iPoint, bl, u); +} + +Matrix<double, 5, 5> ViscFluxes::ComputeJacobian(size_t iPoint, BLRegion *bl, Vector<double, 5> &sysRes, double eps) +{ + unsigned int nVar = bl->GetnVar(); + Matrix<double, 5, 5> JacMatrix; + std::vector<double> uUp; + for (size_t k=0; k<nVar; ++k){ + uUp.push_back(bl->U[iPoint*nVar + k]); + } // End for + + for (size_t iVar=0; iVar<nVar; ++iVar){ + double varSave = uUp[iVar]; + uUp[iVar] += eps; + + JacMatrix.col(iVar) = (BLlaws(iPoint, bl, uUp) - sysRes) / eps; + + uUp[iVar] = varSave; + } + return JacMatrix; +} + +Vector<double, 5> ViscFluxes::BLlaws(size_t iPoint, BLRegion *bl, std::vector<double> u) +{ + unsigned int nVar = bl->GetnVar(); + + Matrix<double, 5, 5> timeMatrix; + Vector<double, 5> spaceVector; + + double dissipRatio; + if (bl->name == "wake"){ + double dissipRatio = 0.9; + } // End if + else{ + double dissiRatio = 1; + } // End else + + bl->Ret[iPoint] = std::max(u[3] * u[0], 1.0); + bl->DeltaStar[iPoint] = u[0] * u[1]; + + /* Boundary layer closure relations */ + + if (bl->Regime[iPoint] == 0){ + LaminarClosures(iPoint, bl); + } // End if + else if (bl->Regime[iPoint] == 1){ + TurbulentClosures(iPoint, bl); + } // End else if + + else{ + std::cout << "Wrong regime\n" << std::endl; + } // End else + + /* Gradients computation */ + double dx = (bl->GetLocMarkers(iPoint) - bl->GetLocMarkers(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->GetVtExt(iPoint) - bl->GetVtExt(iPoint))/dx; + double ddeltaStarExt_dx = (bl->GetDeltaStarExt(iPoint) - bl->GetDeltaStarExt(iPoint))/dx; + + double c=4/(M_PI*dx); + double cExt=4/(M_PI*(bl->GetXxExt(iPoint) - bl->GetXxExt(iPoint-1))); + + /* Amplification routine */ + double dN_dx; + double Ax; + + if (bl->xtrF!=NULL && bl->Regime[iPoint] == 0){ + double Ax = AmplificationRoutine(bl->Hk[iPoint], bl->Ret[iPoint], u[0]); + double dN_dx = (bl->U[iPoint * nVar + 2] - bl->U[(iPoint-1)*nVar + 2])/(bl->GetLocMarkers(iPoint) - bl->GetLocMarkers(iPoint-1)); + + } // End if + else{ + double Ax = 0; + double dN_dx = 0; + } // End else + + double Mea = bl->GetMe(iPoint); + + double Reta = bl->Ret[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 Usa = bl->Us[iPoint]; + + /* Space part */ + + spaceVector(0) = dT_dx + (2 + u[1] - Mea * Mea) * (u[0]/u[3]) * due_dx - Cfa; + spaceVector(1) = u[1] * 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*(bl->Cteq[iPoint] - 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); + } // End if + else{ + spaceVector(4) = 0; + } + + /* Time part */ + + timeMatrix(0,0) = u[1]/u[3]; + timeMatrix(0,1) = u[0]/u[3]; + timeMatrix(0,2) = 0; + timeMatrix(0,3) = u[0]*u[1]/(u[3]*u[3]); + timeMatrix(0,4) = 0; + + timeMatrix(1,0) = (1+u[1]*(1-Hstara))/u[3]; + timeMatrix(1,1) = (1-Hstara)*u[1]/u[3]; + timeMatrix(1,2) = 0; + timeMatrix(1,3) = (2-Hstara*u[1])*u[0]/(u[3]*u[3]); + timeMatrix(1,4) = 0; + + timeMatrix(2,0) = 0; + timeMatrix(2,1) = 0; + timeMatrix(2,2) = 1; + timeMatrix(2,3) = 0; + timeMatrix(2,4) = 0; + + timeMatrix(3,0) = -c*u[1]; + timeMatrix(3,1) = -c*u[0]; + timeMatrix(3,2) = 0; + timeMatrix(3,3) = 1; + timeMatrix(3,4) = 0; + + timeMatrix(4,0) = 0; + timeMatrix(4,1) = 0; + timeMatrix(4,2) = 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,3) = 0; + timeMatrix(4,4) = 0; + } + + Vector<double, 5> sysRes = timeMatrix.partialPivLu().solve(spaceVector); + return sysRes; +} + +double ViscFluxes::AmplificationRoutine(double Hk, double Ret, double theta) +{ + double Ax; + + double Dgr = 0.08; + double Hk1 = 3.5; + double Hk2 = 4; + double Hmi = (1/(Hk-1)); + double logRet_crit = 2.492*pow(1/(Hk-1),0.43) + 0.7*(tanh(14*Hmi-9.24)+1.0); // Value at which the amplification starts to grow + if (Ret <=0){ + Ret = 1; + } + if (log10(Ret) < logRet_crit - Dgr){ + Ax = 0; + } + else{ + double Rnorm = (log10(Ret) - (logRet_crit-Dgr))/(2*Dgr); + double Rfac; + if(Rnorm <=0){ + Rfac = 0; + } + else if(Rnorm >= 1){ + Rfac = 1; + } + else{ + 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*exp(-20*Hmi); + double arg = 3.87*Hmi-2.52; + double dndRet = 0.028*(Hk-1)-0.0345*exp(-(arg*arg)); + Ax = (m*dndRet/theta)*Rfac; + // Set correction for separated profiles + if(Hk > Hk1){ + double Hnorm = (Hk - Hk1)/(Hk2-Hk1); + double Hfac; + if(Hnorm >=1){ + Hfac = 1; + } + else{ + Hfac = 3*Hnorm*Hnorm - 2*Hnorm*Hnorm*Hnorm; + } + double Ax1 = Ax; + double Gro = 0.3+0.35*exp(-0.15*(Hk-5)); + double Tnr = tanh(1.2*(log10(Ret)-Gro)); + double Ax2 = (0.086*Tnr - 0.25/pow(Hk-1,1.5))/theta; + if(Ax2 < 0){ + Ax2 = 0; + } + Ax = Hfac*Ax2 + (1-Hfac)*Ax1; + Ax = std::max(Ax, 0.0); + } + } + return Ax; +} + +void ViscFluxes::LaminarClosures(size_t iPoint, BLRegion *bl) +{ + unsigned int nVar = bl->GetnVar(); + double theta = bl->U[iPoint*nVar+0]; + double H = bl->U[iPoint*nVar+1]; + double Ret = bl->Ret[iPoint]; + double Me = bl->GetMe(iPoint); + double Hk = (H - 0.29*Me*Me)/(1+0.113*Me*Me); // Kinematic shape factor + if(bl->name == "airfoil"){ + Hk = std::max(Hk, 1.02); + } + else{ + Hk = std::max(Hk, 1.00005); + } + Hk = std::min(Hk,6.0); + double Hstar2 = (0.064/(Hk-0.8)+0.251)*Me*Me; // Density shape parameter + double delta = std::min((3.15+ H + (1.72/(Hk-1)))*theta, 12*theta); + double Hks = Hk - 4.35; + double Hstar; + if(Hk <= 4.35){ + double dens = Hk + 1; + Hstar = 0.0111*Hks*Hks/dens - 0.0278*Hks*Hks*Hks/dens + 1.528 -0.0002*(Hks*Hk)*(Hks*Hk); + } + else if(Hk > 4.35){ + Hstar = 1.528 + 0.015*Hks*Hks/Hk; + } + Hstar = (Hstar + 0.028*Me*Me)/(1+0.014*Me*Me); // Whitfield's minor additional compressibility correction + + /* Cf */ + + double Cf; + if(Hk < 5.5){ + double tmp = (5.5-Hk)*(5.5-Hk)*(5.5-Hk) / (Hk+1); + Cf = (-0.07 + 0.0727*tmp)/Ret; + } + else if(Hk >= 5.5){ + double tmp = 1 - 1/(Hk-4.5); + Cf = (-0.07 + 0.015*tmp*tmp) /Ret; + } + + /* Cd */ + + double Cd; + if(Hk < 4){ + Cd = ( 0.00205*pow(4.0-Hk, 5.5) + 0.207 ) * (Hstar/(2*Ret)); + } + else if(Hk >= 4){ + double HkCd = (Hk-4)*(Hk-4); + double denCd = 1+0.02*HkCd; + Cd = ( -0.0016*HkCd/denCd + 0.207) * (Hstar/(2*Ret)); + } + if (bl->name == "wake"){ + Cd = 2*(1.10*(1.0-1.0/Hk)*(1.0-1.0/Hk)/Hk)* (Hstar/(2*Ret)); + Cf = 0; + } + bl->Cd[iPoint] = Cd; + bl->Cf[iPoint] = Cf; + bl->Delta[iPoint] = delta; + bl->Hstar[iPoint] = Hstar; + bl->Hstar2[iPoint] = Hstar2; + bl->Hk[iPoint] = Hk; + bl->Cteq[iPoint] = 0; + bl->Us[iPoint] = 0; +} + +void ViscFluxes::TurbulentClosures(size_t iPoint, BLRegion *bl) +{ + unsigned int nVar = bl->GetnVar(); + double theta = bl->U[iPoint*nVar+0]; + double H = bl->U[iPoint*nVar+1]; + double Ct = bl->U[iPoint*nVar+4]; + double Ret = bl->Ret[iPoint]; + double Me = bl->GetMe(iPoint); + + H = std::max(H, 1.0005); + /* Eliminate absurd transients */ + Ct = std::max(std::min(Ct, 0.30), 0.0000001); + double Hk = (H - 0.29*Me*Me)/(1+0.113*Me*Me); + Hk = std::max(std::min(Hk, 10.0), 1.00005); + double Hstar2 = ((0.064/(Hk-0.8))+0.251)*Me*Me; + //gam = 1.4 - 1 + //Fc = np.sqrt(1+0.5*gam*Me**2) + double Fc = sqrt(1+0.2*Me*Me); + + double H0; + if(Ret <= 400){ + H0 = 4; + } + else if(Ret > 400){ + H0 = 3 + (400/Ret); + } + + Ret = std::max(Ret, 200.0); + double Hstar; + 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 if (Hk > H0){ + Hstar = (Hk-H0)*(Hk-H0)*(0.007*log(Ret)/((Hk-H0+4/log(Ret))*(Hk-H0+4/log(Ret))) + 0.015/Hk) + 1.5 + 4/Ret; + } + + Hstar = (Hstar + 0.028*Me*Me)/(1+0.014*Me*Me); // Whitfield's minor additional compressibility correction + //logRt = np.log(Ret/Fc) + //logRt = max(logRt,3) + //arg = max(-1.33*Hk, -20) + double Us = (Hstar/2)*(1-4*(Hk-1)/(3*H)); // Equivalent normalized wall slip velocity + double delta = std::min((3.15+ H + (1.72/(Hk-1)))*theta, 12*theta); + double Ctcon = 0.5/(6.7*6.7*0.75); + + int n; + double Cf; + double Hkc; + double Cdw; + double Cdd; + double Cdl; + double Cteq; + double Hmin; + double Fl; + double Dfac; + + if (bl->name == "wake"){ + Us = std::min(Us, 0.99995); + n = 2; // two wake halves + Cf = 0; // no friction inside the wake + Hkc = Hk - 1; + Cdw = 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 = 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; + } // End if + n = 1; + // Cf = (1/Fc)*(0.3*np.exp(arg)*(logRt/2.3026)**(-1.74-0.31*Hk)+0.00011*(np.tanh(4-(Hk/0.875))-1)) + Cf = 1/Fc*(0.3*exp(-1.33*Hk)*pow(log10(Ret/Fc),-1.74-0.31*Hk) + 0.00011*(tanh(4-Hk/0.875) - 1)); + Hkc = std::max(Hk-1-18/Ret, 0.01); + // Dissipation coefficient + Hmin = 1 + 2.1/log(Ret); + Fl = (Hk-1)/(Hmin-1); + Dfac = 0.5+0.5*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 = sqrt(Hstar*Ctcon*((Hk-1)*Hkc*Hkc)/((1-Us)*(Hk*Hk)*H)); // Here it is Cteq^0.5 + } // End else + double Cd = n*(Cdw+ Cdd + Cdl); + // Ueq = 1.25/Hk*(Cf/2-((Hk-1)/(6.432*Hk)*((Hk-1)/(6.432*Hk))); + bl->Cd[iPoint] = Cd; + bl->Cf[iPoint] = Cf; + bl->Delta[iPoint] = delta; + bl->Hstar[iPoint] = Hstar; + bl->Hstar2[iPoint] = Hstar2; + bl->Hk[iPoint] = Hk; + bl->Cteq[iPoint] = Cteq; + bl->Us[iPoint] = Us; +} \ No newline at end of file diff --git a/dart/src/wViscFluxes.h b/dart/src/wViscFluxes.h new file mode 100644 index 0000000000000000000000000000000000000000..8e9ac8ef9fe59096aa9b93e8c3cd5d4521f83b9a --- /dev/null +++ b/dart/src/wViscFluxes.h @@ -0,0 +1,28 @@ +#ifndef WViscFluxes_H +#define WViscFluxes_H + +#include "dart.h" +#include "wBLRegion.h" +#include <Eigen/Dense> +#include <vector> +#include <string> + +namespace dart +{ + +class DART_API ViscFluxes +{ +public: + ViscFluxes(); + ~ViscFluxes(); + Eigen::Vector<double, 5> ComputeFluxes(size_t iPoint, BLRegion *bl); + Eigen::Matrix<double, 5, 5> ComputeJacobian(size_t iPoint, BLRegion *bl, Eigen::Vector<double, 5> &sysRes, double eps); +private: + Eigen::Vector<double, 5> BLlaws(size_t iPoint, BLRegion *bl, std::vector<double> u); + double AmplificationRoutine(double hk, double ret, double theta); + void LaminarClosures(size_t iPoint, BLRegion *bl); + void TurbulentClosures(size_t iPoint, BLRegion *bl); + +}; +} // namespace dart +#endif //WViscFluxes_H \ No newline at end of file diff --git a/dart/src/wViscSolver.cpp b/dart/src/wViscSolver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0ba78fd28f634469afb37ffa462b03d446e81151 --- /dev/null +++ b/dart/src/wViscSolver.cpp @@ -0,0 +1,110 @@ +#include "wViscSolver.h" +#include "wBLRegion.h" +#include "wTimeSolver.h" +#include <iostream> +#include <vector> + + +using namespace tbox; +using namespace dart; + + +ViscSolver::ViscSolver(double _Re, double _Minf, double _CFL0) +{ + + /* Freestream parameters */ + Re = _Re; + Minf = _Minf; + + /* User input numerical parameters */ + CFL0 = _CFL0; + + /* Parameters */ + double cd = 0.0; + + std::cout << "--- Viscous solver setup ---\n" + << "Reynolds number: " << Re + << "Freestream Mach number: " << Minf + << "Initial CFL number: " << CFL0 + << std::endl; + + /* Initialzing boundary layer */ + + //std::vector<dart::BLRegion> bl; + + std::cout << "--- Jusqu'ici ok ---\n" << std::endl; + + for (size_t i=0; i<3; ++i) + { + std::cout << "yop" << std::endl; + BLRegion *region = new BLRegion(); + std::cout << "yop2" << std::endl; + bl.push_back(region); + } // end for + + tSolver = new TimeSolver(CFL0, Minf); + + bl[0]->name = "upper"; + bl[1]->name = "lower"; + bl[2]->name = "wake"; + + std::cout << " Boundary layer initialized.\n" << std::endl; + +} // end ViscSolver + + +ViscSolver::~ViscSolver() +{ + for (size_t i=0; i<bl.size(); ++i){ + delete bl[i]; + } // end for + + delete tSolver; + + std::cout << "~ViscSolver()\n"; + + +} // end ~ViscSolver + +void ViscSolver::InitMeshes(size_t region, std::vector<double> locM, std::vector<double> globM) +{ + bl[region]->SetMesh(locM, globM); +} + +void ViscSolver::SetInvBC(size_t region, std::vector<double> _Ue, + std::vector<double> _Me, + std::vector<double> _Rhoe) +{ + bl[region]->SetInvBC(_Ue, _Me, _Rhoe); +} + + +int ViscSolver::Run(){ + std::cout << "Entered run" + << std::endl; + + /* Set boundary condition */ + + bl[0]->SetStagBC(Re); + bl[1]->SetStagBC(Re); + + /* Loop over the regions */ + + for (size_t iRegion = 0; iRegion < bl.size(); ++iRegion){ + + /* Loop over points */ + + for (size_t iPoint = 1; iPoint < bl[iRegion]->GetnMarkers(); ++iPoint){ + + tSolver->InitialCondition(iPoint, bl[iRegion]); + + std::cout << "Point " << iPoint << " H " << bl[iRegion]->U[iPoint*bl[iRegion]->GetnVar() + 3] << std::endl; + + //tSolver->Integration(iPoint, bl[iRegion]); + + } + + + } + return 0; // Successfull exit +}; \ No newline at end of file diff --git a/dart/src/wViscSolver.h b/dart/src/wViscSolver.h new file mode 100644 index 0000000000000000000000000000000000000000..5a369f480d4b07620b19963dbe2fd9aeb6bc8290 --- /dev/null +++ b/dart/src/wViscSolver.h @@ -0,0 +1,38 @@ +#ifndef WVISCSOLVER_H +#define WVISCSOLVER_H + +#include "dart.h" +#include "wBLRegion.h" + +namespace dart +{ + +class DART_API ViscSolver +{ +public: + double cd; + +private: + double Re; + double Minf; + double CFL0; + + TimeSolver *tSolver; + +public: + std::vector<BLRegion *> bl; + + ViscSolver(double _Re, double _Minf, double _CFL0); + + ~ViscSolver(); + void InitMeshes(size_t region, std::vector<double> locM, std::vector<double> globM); + void SetInvBC(size_t region, std::vector<double> _Ue, + std::vector<double> _Me, + std::vector<double> _Rhoe); + + + int Run(); + +}; +} // namespace dart +#endif //WVISCSOLVER_H \ No newline at end of file diff --git a/dart/tests/bliTransonic.py b/dart/tests/bliTransonic.py index c29ee906ffb6d1829ea00f41e0ff26c0e5e64264..f65132bf5140085e838e3bd3c6c985e7cb43c8d5 100755 --- a/dart/tests/bliTransonic.py +++ b/dart/tests/bliTransonic.py @@ -62,9 +62,9 @@ def main(): # define flow variables Re = 1e7 alpha = 2*math.pi/180 - M_inf = 0.73 + M_inf = 0.715 - user_xtr=[0, 0] + user_xtr=[0.43, None] user_Ti=None mapMesh = 1 diff --git a/dart/tests/blicpp.py b/dart/tests/blicpp.py new file mode 100644 index 0000000000000000000000000000000000000000..8391d1f52c94c7d5bca46afb408361614aaf1d98 --- /dev/null +++ b/dart/tests/blicpp.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Copyright 2020 University of Liège +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +## Compute lifting (linear or nonlinear) viscous flow around a NACA 0012 +# Amaury Bilocq +# +# Test the viscous-inviscid interaction scheme +# Reference to the master's thesis: http://hdl.handle.net/2268/252195 +# Reference test cases with Naca0012 (different from master's thesis): +# 1) Incompressible: Re = 1e7, M_inf = 0, alpha = 5°, msTE = 0.01, msLE = 0.01 +# -> nIt = 27, Cl = 0.55, Cd = 0.0058, xtrTop = 0.087, xtrBot = 0.741 +# -> msLe = 0.001, xtrTop = 0.061 +# 2) Compressible: Re = 1e7, M_inf = 5, alpha = 5°, msTE = 0.01, msLE = 0.01 +# -> nIt = 33, Cl = 0.65, Cd = 0.0063, xtrTop = 0.057, xtrBot = 0.740 +# 3) Separated: Re = 1e7, M_inf = 0, alpha = 12°, msTE = 0.01, msLE = 0.001 +# -> nIt = 43, Cl = 1.30 , Cd = 0.0108, xtrTop = 0.010, xtrBot = 1 +# +# CAUTION +# This test is provided to ensure that the solver works properly. +# Mesh refinement may have to be performed to obtain physical results. + +import dart.utils as floU +import dart.default as floD + +import dart.vCoupler as floVC + +import tbox +import tbox.utils as tboxU +import fwk +from fwk.testing import * +from fwk.coloring import ccolors + +import math + +def main(): + print('Start') + # timer + tms = fwk.Timers() + tms['total'].start() + + # define flow variables + Re = 1e7 + alpha = 0.*math.pi/180 + M_inf = 0. + + #user_xtr=[0.41,0.41] + #user_xtr=[0,None] + user_xtr=[None,None] + user_Ti=None + + mapMesh = 0 + nFactor = 3 + + # Time solver parameters + Time_Domain = True # True for unsteady solver, False for steady solver + CFL0 = 5 + + # ======================================================================================== + + U_inf = [math.cos(alpha), math.sin(alpha)] # norm should be 1 + c_ref = 1 + dim = 2 + tol = 1e-4 # tolerance for the VII (usually one drag count) + case='Case1FreeTrans.dat' # File containing results from XFOIL of the considered case + + # mesh the geometry + print(ccolors.ANSI_BLUE + 'PyMeshing...' + ccolors.ANSI_RESET) + tms['msh'].start() + pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.01, 'msLe' : 0.01} + #pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.002, 'msLe' : 0.0001} + msh, gmshWriter = floD.mesh(dim, 'models/n0012.geo', pars, ['field', 'airfoil', 'downstream']) + tms['msh'].stop() + + # set the problem and add medium, initial/boundary conditions + tms['pre'].start() + pbl, _, _, bnd, blw = floD.problem(msh, dim, alpha, 0., M_inf, c_ref, c_ref, 0.25, 0., 0., 'airfoil', te = 'te', vsc = True, dbc=True) + tms['pre'].stop() + + # solve viscous problem + + print(ccolors.ANSI_BLUE + 'PySolving...' + ccolors.ANSI_RESET) + tms['solver'].start() + + isolver = floD.newton(pbl) + vsolver = floD.initBL(Re, M_inf, CFL0) + + coupler = floVC.Coupler(isolver, vsolver) + + coupler.CreateProblem(blw[0], blw[1]) + + coupler.Run() + tms['solver'].stop() + + # extract Cp + Cp = floU.extract(bnd.groups[0].tag.elems, isolver.Cp) + tboxU.write(Cp, 'Cp_airfoil.dat', '%1.5e', ', ', 'x, y, z, Cp', '') + # display results + print(ccolors.ANSI_BLUE + 'PyRes...' + ccolors.ANSI_RESET) + print(' Re M alpha Cl Cd Cdp Cdf Cm') + print('{0:6.1f}e6 {1:8.2f} {2:8.1f} {3:8.4f} {4:8.4f} {5:8.4f} {6:8.4f} {7:8.4f}'.format(Re/1e6, M_inf, alpha*180/math.pi, isolver.Cl, vsolver.Cd, vsolver.Cdp, vsolver.Cdf, isolver.Cm)) + + # display timers + tms['total'].stop() + print(ccolors.ANSI_BLUE + 'PyTiming...' + ccolors.ANSI_RESET) + print('CPU statistics') + print(tms) + + + + # visualize solution and plot results + floD.initViewer(pbl) + tboxU.plot(Cp[:,0], Cp[:,3], 'x', 'Cp', 'Cl = {0:.{3}f}, Cd = {1:.{3}f}, Cm = {2:.{3}f}'.format(isolver.Cl, vsolver.Cd, isolver.Cm, 4), True) + + val=validation.Validation(case) + val.main(isolver.Cl,vsolver.wData) + + + # check results + print(ccolors.ANSI_BLUE + 'PyTesting...' + ccolors.ANSI_RESET) + tests = CTests() + if Re == 1e7 and M_inf == 0.2 and alpha == 5*math.pi/180: + tests.add(CTest('Cl', isolver.Cl, 0.56, 5e-2)) # XFOIL 0.58 + tests.add(CTest('Cd', vsolver.Cd, 0.0063, 1e-3, forceabs=True)) # XFOIL 0.00617 + tests.add(CTest('Cdp', vsolver.Cdp, 0.0019, 1e-3, forceabs=True)) # XFOIL 0.00176 + tests.add(CTest('xtr_top', vsolver.xtr[0], 0.059, 0.03, forceabs=True)) # XFOIL 0.0510 + tests.add(CTest('xtr_bot', vsolver.xtr[1], 0.738, 0.03, forceabs=True)) # XFOIL 0.7473 + else: + raise Exception('Test not defined for this flow') + + tests.run() + + + # eof + print('') + +if __name__ == "__main__": + main() diff --git a/dart/vCoupler.py b/dart/vCoupler.py new file mode 100644 index 0000000000000000000000000000000000000000..8a575f0732bb7db28b8293c55acd9b8d1406e996 --- /dev/null +++ b/dart/vCoupler.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Copyright 2020 University of Liège +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +## VII Coupler +# Paul Dechamps + +from dart.viscous.Master.DAirfoil import Airfoil +from dart.viscous.Master.DWake import Wake +from dart.viscous.Drivers.DGroupConstructor import GroupConstructor + +from fwk.coloring import ccolors + +import numpy as np + +class Coupler: + def __init__(self, iSolver, vSolver) -> None: + self.iSolver=iSolver + self.vSolver=vSolver + + self.maxCouplIter = 2 + self.couplTol = 1e-4 + pass + + def CreateProblem(self, _boundaryAirfoil, _boundaryWake): + + self.group = [Airfoil(_boundaryAirfoil), Wake(_boundaryWake)] # airfoil and wake python objects + pass + + def Run(self): + + # Initilize meshes in c++ objects + + couplIter = 0 + while couplIter < self.maxCouplIter: + + cdPrev = 0 + + # Run inviscid solver + + self.iSolver.run() + + # Extract inviscid boundary + + for n in range(0, len(self.group)): + + for i in range(0, len(self.group[n].boundary.nodes)): + + self.group[n].v[i,0] = self.iSolver.U[self.group[n].boundary.nodes[i].row][0] + self.group[n].v[i,1] = self.iSolver.U[self.group[n].boundary.nodes[i].row][1] + self.group[n].v[i,2] = self.iSolver.U[self.group[n].boundary.nodes[i].row][2] + self.group[n].Me[i] = self.iSolver.M[self.group[n].boundary.nodes[i].row] + self.group[n].rhoe[i] = self.iSolver.rho[self.group[n].boundary.nodes[i].row] + + dataIn=[None,None] + for n in range(0,len(self.group)): + self.group[n].connectListNodes, self.group[n].connectListElems, dataIn[n] = self.group[n].connectList() + fMeshDict, cMeshDict, data = GroupConstructor().mergeVectors(dataIn, 0, 1) + if couplIter == 0: + # Initialize mesh + self.vSolver.InitMeshes(0, fMeshDict['locCoord'][:fMeshDict['bNodes'][1]], fMeshDict['globCoord'][:fMeshDict['bNodes'][1]]) + self.vSolver.InitMeshes(1, fMeshDict['locCoord'][fMeshDict['bNodes'][1]:fMeshDict['bNodes'][2]], fMeshDict['globCoord'][fMeshDict['bNodes'][1]:fMeshDict['bNodes'][2]]) + self.vSolver.InitMeshes(2, fMeshDict['locCoord'][fMeshDict['bNodes'][2]:], fMeshDict['globCoord'][fMeshDict['bNodes'][2]:]) + print('fro mpy : Mesh ok') + self.vSolver.SetInvBC(0, fMeshDict['vtExt'][:fMeshDict['bNodes'][1]], fMeshDict['Me'][:fMeshDict['bNodes'][1]], fMeshDict['rho'][:fMeshDict['bNodes'][1]]) + self.vSolver.SetInvBC(1, fMeshDict['vtExt'][fMeshDict['bNodes'][1]:fMeshDict['bNodes'][2]], fMeshDict['Me'][fMeshDict['bNodes'][1]:fMeshDict['bNodes'][2]], fMeshDict['rho'][fMeshDict['bNodes'][1]:fMeshDict['bNodes'][2]]) + self.vSolver.SetInvBC(2, fMeshDict['vtExt'][fMeshDict['bNodes'][2]:], fMeshDict['Me'][fMeshDict['bNodes'][2]:], fMeshDict['rho'][fMeshDict['bNodes'][2]:]) + print('from py: InvBC ok') + # Run viscous solver + + exitCode = self.vSolver.Run() + print('From python exitcode: ', exitCode) + + error = (self.vSolver.cd - cdPrev)/self.vSolver.cd if self.vSolver.cd != 0 else 1 + + if error <= self.couplTol: + print('') + print(ccolors.ANSI_GREEN, 'It: {:<3.0f} Cd = {:<6.5f}. Error = {:<2.3f} < {:<2.3f}' + .format(couplIter, self.vsolver.cd, np.log10(error), np.log10(self.couplTol)), ccolors.ANSI_RESET) + print('') + return 0 + + print('') + print(ccolors.ANSI_BLUE, 'It: {:<3.0f} Cd = {:<6.5f}. Error = {:<2.3f} > {:<2.3f}' + .format(couplIter, self.vSolver.cd, np.log10(error), np.log10(self.couplTol)), ccolors.ANSI_RESET) + print('') + + # Set inviscid boundary condition + + for n in range(0, len(self.group)): + + for i in range(0, self.group[n].nE): + + self.group[n].boundary.setU(i, self.group[n].u[i]) + + couplIter += 1 + else: + print(ccolors.ANSI_RED, 'Maximum number of {:<.0f} coupling iterations reached'.format(self.maxCouplIter), ccolors.ANSI_RESET) + return couplIter + diff --git a/dart/viscous/Drivers/DGroupConstructor.py b/dart/viscous/Drivers/DGroupConstructor.py index 44877c7d62e24180c383d8319156baa755c36ed9..cb6d02c925a2736334e5110b99580da1b919a2a2 100755 --- a/dart/viscous/Drivers/DGroupConstructor.py +++ b/dart/viscous/Drivers/DGroupConstructor.py @@ -42,38 +42,38 @@ class GroupConstructor(): if mapMesh: # Save initial mesh. - cMesh = np.concatenate((dataIn[0][0][:,0], dataIn[0][1][1:,0], dataIn[1][:,0])) - cMeshbNodes = [0, len(dataIn[0][0][:,0]), len(dataIn[0][0][:,0]) + len(dataIn[0][1][1:,0])] + cMesh = np.concatenate((dataIn[0][0][:,0], dataIn[0][1][:,0], dataIn[1][:,0])) + cMeshbNodes = [0, len(dataIn[0][0][:,0]), len(dataIn[0][0][:,0]) + len(dataIn[0][1][:,0])] cxx = np.concatenate((xx_up, xx_lw[1:], xx_wk)) cvtExt = np.concatenate((vtExt_up, vtExt_lw[1:], vtExt_wk)) - cxxExt = np.concatenate((dataIn[0][0][:,8], dataIn[0][1][1:,8],dataIn[1][:,8])) + cxxExt = np.concatenate((dataIn[0][0][:,8], dataIn[0][1][:,8],dataIn[1][:,8])) # Create fine mesh. fMeshUp = self.createFineMesh(dataIn[0][0][:,0], nFactor) fMeshLw = self.createFineMesh(dataIn[0][1][:,0], nFactor) fMeshWk = self.createFineMesh(dataIn[1][:,0] , nFactor) - fMesh = np.concatenate((fMeshUp, fMeshLw[1:], fMeshWk)) - fMeshbNodes = [0, len(fMeshUp), len(fMeshUp) + len(fMeshLw[1:])] + fMesh = np.concatenate((fMeshUp, fMeshLw, fMeshWk)) + fMeshbNodes = [0, len(fMeshUp), len(fMeshUp) + len(fMeshLw)] fxx_up = self.interpolateToFineMesh(xx_up, fMeshUp, nFactor) fxx_lw = self.interpolateToFineMesh(xx_lw, fMeshLw, nFactor) fxx_wk = self.interpolateToFineMesh(xx_wk, fMeshWk, nFactor) - fxx = np.concatenate((fxx_up, fxx_lw[1:], fxx_wk)) + fxx = np.concatenate((fxx_up, fxx_lw, fxx_wk)) fvtExt_up = self.interpolateToFineMesh(vtExt_up, fMeshUp, nFactor) fvtExt_lw = self.interpolateToFineMesh(vtExt_lw, fMeshLw, nFactor) fvtExt_wk = self.interpolateToFineMesh(vtExt_wk, fMeshWk, nFactor) - fvtExt = np.concatenate((fvtExt_up, fvtExt_lw[1:], fvtExt_wk)) + fvtExt = np.concatenate((fvtExt_up, fvtExt_lw, fvtExt_wk)) fMe_up = self.interpolateToFineMesh(dataIn[0][0][:,5], fMeshUp, nFactor) fMe_lw = self.interpolateToFineMesh(dataIn[0][1][:,5], fMeshLw, nFactor) fMe_wk = self.interpolateToFineMesh(dataIn[1][:,5] , fMeshWk, nFactor) - fMe = np.concatenate((fMe_up, fMe_lw[1:], fMe_wk)) + fMe = np.concatenate((fMe_up, fMe_lw, fMe_wk)) frho_up = self.interpolateToFineMesh(dataIn[0][0][:,6], fMeshUp, nFactor) frho_lw = self.interpolateToFineMesh(dataIn[0][1][:,6], fMeshLw, nFactor) frho_wk = self.interpolateToFineMesh(dataIn[1][:,6] , fMeshWk, nFactor) - frho = np.concatenate((frho_up, frho_lw[1:], frho_wk)) + frho = np.concatenate((frho_up, frho_lw, frho_wk)) fdStarExt_up = self.interpolateToFineMesh(dataIn[0][0][:,7], fMeshUp, nFactor) fdStarExt_lw = self.interpolateToFineMesh(dataIn[0][1][:,7], fMeshLw, nFactor) @@ -83,17 +83,17 @@ class GroupConstructor(): fxxExt_lw = self.interpolateToFineMesh(dataIn[0][1][:,8], fMeshLw, nFactor) fxxExt_wk = self.interpolateToFineMesh(dataIn[1][:,8] , fMeshWk, nFactor) - fdStarext = np.concatenate((fdStarExt_up, fdStarExt_lw[1:], fdStarExt_wk)) - fxxext = np.concatenate((fxxExt_up, fxxExt_lw[1:], fxxExt_wk)) + fdStarext = np.concatenate((fdStarExt_up, fdStarExt_lw, fdStarExt_wk)) + fxxext = np.concatenate((fxxExt_up, fxxExt_lw, fxxExt_wk)) - fdv = np.concatenate((dv_up, dv_lw[1:], dv_wk)) + fdv = np.concatenate((dv_up, dv_lw, dv_wk)) fMeshDict = {'globCoord': fMesh, 'bNodes': fMeshbNodes, 'locCoord': fxx, 'vtExt': fvtExt, 'Me': fMe, 'rho': frho, 'deltaStarExt': fdStarext, 'xxExt': fxxext, 'dv': fdv} - cMe = np.concatenate((dataIn[0][0][:,5], dataIn[0][1][1:,5], dataIn[1][:,5])) - cRho = np.concatenate((dataIn[0][0][:,6], dataIn[0][1][1:,6], dataIn[1][:,6])) - cdStarExt = np.concatenate((dataIn[0][0][:,7], dataIn[0][1][1:,7], dataIn[1][:,7])) + cMe = np.concatenate((dataIn[0][0][:,5], dataIn[0][1][:,5], dataIn[1][:,5])) + cRho = np.concatenate((dataIn[0][0][:,6], dataIn[0][1][:,6], dataIn[1][:,6])) + cdStarExt = np.concatenate((dataIn[0][0][:,7], dataIn[0][1][:,7], dataIn[1][:,7])) cMeshDict = {'globCoord': cMesh, 'bNodes': cMeshbNodes, 'locCoord': cxx, 'vtExt': cvtExt, 'Me': cMe, 'rho': cRho, 'deltaStarExt': cdStarExt, 'xxExt': cxxExt, 'dv': fdv} @@ -112,7 +112,7 @@ class GroupConstructor(): else: - Mesh = np.concatenate((dataIn[0][0][:,0], dataIn[0][1][1:,0], dataIn[1][:,0])) + Mesh = np.concatenate((dataIn[0][0][:,0], dataIn[0][1][:,0], dataIn[1][:,0])) MeshbNodes = [0, len(dataIn[0][0][:,0]), len(dataIn[0][0][:,0]) + len(dataIn[0][1][1:,0])] xx = np.concatenate((xx_up, xx_lw[1:], xx_wk))