Subversion Repositories channelflow

[/] [trunk/] [examples/] [channel.cpp] - Rev 375

Compare with Previous | Blame | View Log

#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include "channelflow/flowfield.h"
#include "channelflow/periodicfunc.h"
#include "channelflow/dns.h"
#include "channelflow/utilfuncs.h"

using namespace std;
using namespace channelflow;

int main() {

  cout << "================================================================\n";
  cout << "This program integrates a plane Poiseuille (channel) flow from \n";
  cout << "a random initial initial condition and saves velocity fields\n";
  cout << "in a data-channel/ directory, in channelflow's binary data file\n";
  cout << "format." << endl << endl;
  const int Nx=128;
  const int Ny=65;
  const int Nz=128;

  const Real Lx=4*pi;
  const Real a= -1.0;
  const Real b=  1.0;
  const Real Lz=2*pi;

  const Real nu = 1.0/4000;

  const Real CFLmin = 0.40;
  const Real CFLmax = 0.60;
  const Real dtmin  = 0.002;
  const Real dtmax  = 0.04;
  const Real dt0    = 0.02;
  const bool variable_dt = true;
  const Real T0 = 0;    // start time
  const Real T1 = 300;  // end time
  const Real dT = 0.25;  // plotting and statistics interval

  DNSFlags flags;
  flags.baseflow     = LaminarBase;
  flags.timestepping = SBDF3;
  flags.dealiasing   = DealiasXZ;
  flags.constraint   = BulkVelocity;
  flags.ulowerwall   = 0.0;
  flags.uupperwall   = 0.0;
  flags.Ubulk        = 2.0/3.0;
  flags.nu           = 1.0/4000.0;
  flags.t0           = 0.0;
  flags.dt           = dt0;

  const Real perturbMag = 0.10;
  const Real decay = 0.7; // cheb spectral decay of perturb profiles
  const int kxmax=3;      // maximum Fourier mode for perturbations
  const int kzmax=3;

  const char sp= ' ';
  const char nl= '\n';

  cout << setprecision(4);
  Vector x = periodicpoints(Nx, Lx);
  Vector y = chebypoints(Ny,a,b);
  Vector z = periodicpoints(Nz, Lz);
  x.save("x");
  y.save("y");
  z.save("z");

  FlowField u(Nx,Ny,Nz,3,Lx,Lz,a,b);
  FlowField q(Nx,Ny,Nz,1,Lx,Lz,a,b);
  u.addPerturbations(kxmax,kzmax,1,decay);
  u *= perturbMag/L2Norm(u);
  //FlowField u("u80");
  //FlowField q("q80");

  FlowField omega(Nx,Ny,Nz,3,Lx,Lz,a,b);

  cout << "optimizing FFTW..." << flush;
  fftw_loadwisdom();
  u.optimizeFFTW();
  fftw_savewisdom();
  cout << "done" << endl;

  cout << "constructing DNS..." << flush;
  TimeStep dt(dt0, dtmin, dtmax, dT, CFLmin, CFLmax, variable_dt);
  DNS dns(u, flags);
  //dns.reset_Ubulk(2.0/3.0);
  cout << "done" << endl;

  // print header info in fmodes.asc file

  ofstream modestream("fmodes.asc");
  ofstream dragstream("drags.asc");

  modestream << "% ";
  for (int kx=-kxmax; kx<=kxmax; ++kx)
    for (int kz=0; kz<=kzmax; ++kz)
      modestream << kx << ',' << kz << sp;
  modestream << nl;

  // prior to timestepping loop set Ubase(y) =  1-y^2 = [T_0(y) - T_2(y)]/2
  ChebyCoeff Ubase(Ny, a,b,Spectral);
  Ubase[0] = 0.5;
  Ubase[2] = -0.5;
  const Real h = (b-a)/2;
  const Real ycenter = (b+a)/2;

  mkdir("data-channel");
  for (Real t=T0; t<=T1; t += dT) {
    cout << "          t == " << t << endl;
    cout << "         dt == " << dt << endl;
    cout << "        CFL == " << dns.CFL() << endl;
    cout << " L2Norm2(u) == " << L2Norm2(u) << endl;
    cout << "divNorm2(u) == " << divNorm(u)/L2Norm(u) << endl;
    cout << "      Ubulk == " << dns.Ubulk() << endl;
    cout << "      ubulk == " << Re(u.profile(0,0,0)).mean()/2 << endl;
    cout << "       dPdx == " << dns.dPdx() << endl;

      // inside timestepping-loop set
    ChebyCoeff U = Re(u.profile(0,0,0));
    U += Ubase;

    Real Reynolds_center = U.eval(ycenter)*h/nu;
    Real Reynolds_mean   = U.mean()*h/nu;

    cout << " centerline Re  == " << Reynolds_center << endl;
    cout << " mean flow  Re  == " << Reynolds_mean << endl;

    const int it = iround(t);
    if (abs(Real(it)-t) < dt && it % 10 == 0) {
      cout << "saving flowfields..." << endl;
      u.save("data-channel/u"+i2s(it));
      q.save("data-channel/q"+i2s(it));
      cout << "done" << endl;
    }

    /*********************************
    u.makePhysical();
    u.saveSlice(2,0,0,"uside");
    u.saveSlice(2,1,0,"vside");
    u.saveSlice(2,2,0,"wside");
    u.saveSlice(0,0,0,"usec");
    u.saveSlice(0,1,0,"vsec");
    u.saveSlice(0,2,0,"wsec");
    u.makeSpectral();
    ********************************/

    /***************
    curl(u, omega);
    omega.saveSlice(0,0,0,"omsec0");
    omega.saveSlice(0,1,0,"omsec1");
    omega.saveSlice(0,2,0,"omsec2");

    for (int kx=-kxmax; kx<=kxmax; ++kx) {
      int mx = u.mx(kx);
      for (int kz=0; kz<=kzmax; ++kz) {
        int mz = u.mz(kz);
        BasisFunc u_kxkz = u.profile(mx,mz);
        modestream << L2Norm(u_kxkz) << sp;
      }
    }
    modestream << endl;
    ChebyCoeff dudy = diff(Re(u.profile(0,0,0)));
    dragstream << nu*dudy.eval_a() << sp << nu*dudy.eval_b() << endl;
    ***************************/

    //ChebyCoeff u00 = Re(u.profile(0,0,0));
    //u00.save("u00_" + i2s(int(t)));

    if (dt.adjust(dns.CFL())) {
      cerr << "Resetting dt to " << dt << ", new CFL == " << dt.CFL() << endl;
      dns.reset_dt(dt);
    }
    dns.advance(u, q, dt.n());
    cout << endl;
  }
  cout << "done!" << endl;
}

Compare with Previous | Blame