#include #include #include #include #include "channelflow/flowfield.h" #include "channelflow/diffops.h" #include "channelflow/symmetry.h" #include "channelflow/utilfuncs.h" using namespace std; using namespace channelflow; Real energy(FlowField& u, int i, bool normalize=true); // returns S,A, for symmetric,antisymmetric to eps accuracy // returns s,a, for symmetric,antisymmetric to sqrt(eps) accuracy char symmetric(const FieldSymmetry& s, const FlowField& u, Real& serr, Real& aerr, Real eps=1e-7); Real project(const FlowField& u, const FieldSymmetry& s, int sign); int main(int argc, char* argv[]) { string purpose("prints information about a FlowField"); ArgList args(argc, argv, purpose); const bool geom = args.getflag("-g", "--geometry", "show geometrical properties"); const bool mean = args.getflag("-m", "--mean", "show mean properties"); const bool norm = args.getflag("-n", "--norm", "show norm properties"); const bool spec = args.getflag("-sp", "--spectral", "show spectral properties"); const bool symm = args.getflag("-sy", "--symmetry", "show symmetry properties"); const bool dyn = args.getflag("-d", "--dynamic", "show dynamical properties"); const bool nrgy = args.getflag("-e", "--energy", "show energy properties"); const Real Reynolds = args.getreal("-R", "--Reynolds", 400, "Reynolds number"); const Real eps = args.getreal("-eps", "--eps", 1e-7, "spectral noise floor"); const Real dt = args.getreal("-dt", "--dt", 0.03125, "integration time for du/dt estimate"); const Real T = args.getreal("-T", "--T", dt, "integration time for du/dt estimate"); const string nlmeth = args.getstr("-nl", "--nonlinearity", "rot", "method for u grad u [rot or skw]"); const int digits = args.getint("-dg", "--digits", 6, "digits of output for reals"); const string uname = args.getstr(1, "", "input field"); args.check(); bool all = (!geom && !mean && !norm && !spec && !symm && !dyn && !nrgy) ? true : false; FlowField u(uname); u.makeSpectral(); const Real unorm = L2Norm(u); cout << setprecision(digits); if (all || geom) { cout << "--------------Geometry------------------" << endl; cout << "Nx == " << u.Nx() << endl; cout << "Ny == " << u.Ny() << endl; cout << "Nz == " << u.Nz() << endl; cout << "Nd == " << u.Nd() << endl; cout << "Lx == " << u.Lx() << endl; cout << "Ly == " << u.Ly() << endl; cout << "Lz == " << u.Lz() << endl; cout << " a == " << u.a() << endl; cout << " b == " << u.b() << endl; cout << "lx == " << u.Lx()/(2*pi) << endl; cout << "lz == " << u.Lz()/(2*pi) << endl; cout << "alpha == " << 2*pi/u.Lx() << endl; cout << "gamma == " << 2*pi/u.Lz() << endl; cout << endl; } if (all || mean) { for (int i=0; i eps) { kxmax = Greater(kxmax, abs(kx)); kzmax = Greater(kzmax, abs(kz)); } for (int ky=0; ky eps) kymax = Greater(kymax, ky); } } } cout << "u.dealiased() == " << (u.dealiased() ? "true" : "false") << endl; cout << "Energy over " << eps << " is confined to : \n"; cout << " |kx| <= " << kxmax << endl; cout << " |ky| <= " << kymax << endl; cout << " |kz| <= " << kzmax << endl; cout << "Minimum aliased grid : " << 2*(kxmax+1) << " x " << kymax+1 << " x " << 2*(kzmax+1) << endl; cout << "Minimum dealiased grid : " << 3*(kxmax+1) << " x " << kymax+1 << " x " << 3*(kzmax+1) << endl; cout << endl; } if (all || nrgy) { ChebyCoeff U(u.Ny(), u.a(), u.b(), Spectral); U[1] = 1; FlowField uU(u); uU += U; cout << "dissip (u) == " << dissipation(u) << endl; cout << "forcing(u) == " << forcing(u) << endl; cout << "energy (u) == " << 0.5*L2Norm2(u) << endl; cout << "dissip (u+U) == " << dissipation(uU) << endl; cout << "forcing(u+U) == " << forcing(uU) << endl; cout << "energy (u+U) == " << 0.5*L2Norm2(uU) << endl; } if (all || dyn) { cout << "------------Dynamics--------------------" << endl; // Construct Navier-Stoke Integrator DNSFlags flags; flags.timestepping = SBDF3; flags.dealiasing = DealiasXZ; flags.constraint = PressureGradient; flags.verbosity = PrintTicks; flags.baseflow = PlaneCouette; flags.dPdx = 0.0; if (nlmeth == "skw") flags.nonlinearity = SkewSymmetric; else if (nlmeth == "div") flags.nonlinearity = Divergence; else if (nlmeth == "cnv") flags.nonlinearity = Convection; else if (nlmeth == "alt") flags.nonlinearity = Alternating; else flags.nonlinearity = Rotational; // Define flow parameters const Real nu = 1.0/Reynolds; const int Nx = u.Nx(); const int Ny = u.Ny(); const int Nz = u.Nz(); const Real Lx = u.Lx(); const Real a = u.a(); const Real b = u.b(); const Real Lz = u.Lz(); //const Real dt = (T < 0.01) ? T : 0.01; const int N = iround(T/dt); // Construct base flow for plane Couette: U(y) = y Vector y = chebypoints(Ny,a,b); FlowField q(Nx,Ny,Nz,1,Lx,Lz,a,b); DNS dns(u, nu, dt, flags, 0.0); cout << "computing du/dt: " << flush; FlowField dudt(u); dns.advance(dudt, q, N); cout << endl; dudt -= u; dudt *= 1.0/(N*dt); cout << "L2Norm(u) == " << L2Norm(u) << endl; cout << "L2Norm(du/dt) == " << L2Norm(dudt) << endl; FlowField dudx; FlowField dudz; xdiff(u,dudx); zdiff(u,dudz); Real dudxnorm = L2Norm(dudx); Real dudznorm = L2Norm(dudz); cout << "L2Norm(du/dx) == " << dudxnorm << endl; cout << "L2Norm(du/dz) == " << dudznorm << endl; Real ueps = 1e-12; dudx *= (dudxnorm < ueps) ? 0.0 : 1.0/dudxnorm; dudz *= (dudznorm < ueps) ? 0.0 : 1.0/dudznorm; Real ax = L2IP(dudt,dudx); Real az = L2IP(dudt,dudz); FlowField Pu(u); Pu.setToZero(); FlowField utmp; utmp = dudx; utmp *= ax; Pu += utmp; utmp = dudz; utmp *= az; Pu += utmp; Real Punorm = L2Norm(Pu); Real waviness = Punorm/L2Norm(dudt); Real theta = acos(L2IP(Pu,dudt)/(L2Norm(dudt)*Punorm)); cout << endl; cout << " waviness == " << waviness << endl; cout << " theta == " << theta << " == " << theta*180/pi << " degrees\n"; cout << endl; cout << "(waviness == fraction of dudt within dudx,dudz tangent plane)\n"; cout << "( theta == angle between dudt and dudx,dudz tangent plane)\n"; cout << endl; } } Real energy(FlowField& u, int i, bool normalize) { assert(u.ystate() == Spectral); assert(u.xzstate()==Spectral); Real sum = 0.0; ComplexChebyCoeff prof(u.Ny(), u.a(), u.b(), Spectral); for (int mx=0; mx0 to take account of kz<0 ghost modes for (int mz=0; mz