int main(int argc, char *argv[]) { # include "setRootCase.H" # include "createTime.H" # include "createMesh.H" Info << "perturbU: generalised velocity perturbation implementation for " << "the initialisation of ducted well-resolved LES flows." << endl; // Xdir -> Ubar - streamwise // Ydir -> wallReflection vectors // Zdir -> cross product Xdir^Ydir // Ubar and Retau should be set in transportProperties // The choice of Retau is not critical as long as it is // approximately the right order of magnitude // A laminar background velocity profile is assumed // with maximum U at h = max(wall distance) // A laminar initial profile is essential since wall normal motion // of a mean turbulent profile without resolved turbulence will // diffuse the perturbations, preventing transition in some cases wallDist yw(mesh); const scalar h = max(yw.internalField()); // local yDir wallDistReflection reflexVec(mesh); const volVectorField yDir = reflexVec.n(); IOobject Uheader ( "U", runTime.timeName(), mesh, IOobject::MUST_READ ); Info << "Reading U" << endl; volVectorField U(Uheader, mesh); IOdictionary transportProperties ( IOobject ( "transportProperties", runTime.constant(), mesh, IOobject::MUST_READ, IOobject::NO_WRITE ) ); dimensionedScalar nu ( transportProperties.lookup("nu") ); dimensionedVector Ubar ( transportProperties.lookup("Ubar") ); dimensionedScalar Retau ( transportProperties.lookup("Retau") ); scalar sigma ( transportProperties.lookupOrDefault<scalar>("sigma", 0.00055) ); Info << " sigma = " << sigma << endl; scalar duplusC ( transportProperties.lookupOrDefault<scalar>("duplusC", 0.25) ); Info << " duplusC = " << duplusC << endl; scalar epsilonC ( transportProperties.lookupOrDefault<scalar>("epsilonC", 0.05) ); Info << " epsilonC = " << epsilonC << endl; scalar deviationC ( transportProperties.lookupOrDefault<scalar>("deviationC", 0.2) ); Info << " deviationC = " << deviationC << endl; vector xDir = Ubar.value() / mag(Ubar.value()); Info << "Re(tau) = " << Retau << endl; const scalar utau = Retau.value() * nu.value() / h; Info << " u(tau) = " << utau << endl; // wall normal circulation const scalar duplus = Ubar.value().x() * duplusC / utau; // spanwise wavenumber: spacing z+ = 200 const scalar betaPlus = 2.0 * 3.14 *(1.0 / 200.0); // streamwise wave number: spacing x+ = 500 const scalar alphaPlus = 2.0 * 3.14 * (1.0 / 500.0); const scalar epsilon = Ubar.value().x() * epsilonC; const vectorField& centres(mesh.C()); Random perturbation(1234567); forAll(centres, celli) { // add a small random component to enhance symmetry breaking scalar deviation = 1.0 + deviationC * perturbation.GaussNormal(); const vector& cCentre = centres[celli]; vector zDir = xDir^yDir[celli]; zDir /= mag(zDir); scalar zplus = (cCentre & zDir) * Retau.value() / h; scalar yplus = yw[celli] * Retau.value() / h; scalar xplus = (cCentre & xDir) * Retau.value() / h; // ML: it seems that this profile (or coefficient before Ubar) // is correct for rectangular shape, for body of // revolution it is (should be?) different // laminar parabolic profile U[celli] = 3.0 * Ubar.value() * (yw[celli] / h - 0.5 * sqr(yw[celli] / h)); // streak streamwise velocity U[celli] += xDir * (utau * duplus / 2.0) * (yplus / 40.0) * Foam::exp(-sigma * Foam::sqr(yplus) + 0.5) * Foam::cos(betaPlus * zplus) * deviation; // streak spanwise perturbation U[celli] += zDir * epsilon * Foam::sin(alphaPlus * xplus) * yplus * Foam::exp(-sigma * Foam::sqr(yplus)) * deviation; }
double* WhiteTest(int obs, int nvar, double* resid, double** X, bool InclConstant) { double *r2 = new double[obs]; int i = 0, jj = 0; // if (!InclConstant) // DevFromMean(obs,resid); // (1) r2 = Compute e2 double r2_bar = 0; for (i=0;i<obs;i++) { r2[i] = geoda_sqr(resid[i]); r2_bar += r2[i]; } r2_bar /= obs; // (2) define (n*n + 3n)/2 memory location for w const int df = InclConstant? (geoda_sqr(nvar-1)+3*(nvar-1))/2 : (geoda_sqr(nvar)+3*nvar)/2; DoublePtr *w = new DoublePtr[df+1]; for (i=0;i<=df;i++) w[i] = new double[obs]; // (3) keep original X into w[1 .. nvar][] int ix = InclConstant? 0 : 1; int k = nvar+ix; for (jj=0;jj<obs;jj++) w[0][jj] = 1.0; if (InclConstant) { for (i=1;i<nvar;i++) { for (jj=0;jj<obs;jj++) w[i][jj] = X[i][jj]; } } else { for (i=0;i<nvar;i++) for (jj=0;jj<obs;jj++) w[i+1][jj] = X[i][jj]; } // (4) Create cross product of Xs and store them into w[nvar ... df][] for (i=1-ix;i<nvar;i++) { for (int j=i; j<nvar;j++) { for (jj=0;jj<obs;jj++) w[k][jj] = X[i][jj] * X[j][jj]; k++; } } // (5) Compute OLS, r2 on w DenseVector yw(r2, obs, false), olsw(k); DenseVector *xw = new DenseVector[k]; for (int cnt = 0; cnt < k; ++cnt) { xw[cnt].absorb(w[cnt], obs, false); } double ** cov = new double * [k]; double *u = new double[obs]; for (i = 0; i < k; i++) { cov[i] = new double [k]; for (jj = 0; jj < k; jj++) { cov[i][jj] = 0; } } double *rsl = new double[3]; rsl[0] = df; rsl[1] = -99999; rsl[2] = -99999; if (!ordinaryLS(yw, xw, cov, u, olsw)) { return rsl; } double s_u = 0.0; for (i=0;i<obs;i++) s_u += geoda_sqr(r2[i] - r2_bar); rsl[1]= obs * ( 1 - (norm(u,obs) / s_u)); // rsl[1]= chicdf(rsl[0],df); rsl[2]= gammp( double (df) / 2.0, rsl[1]/2.0 ); return rsl; }