int main(int argc, char* argv[]) {
    plbInit(&argc, &argv);
    global::directories().setOutputDir("./tmp/");

    MultiBlockLattice2D<T, DESCRIPTOR> lattice (
           nx, ny, new BGKdynamics<T,DESCRIPTOR>(omega) );

    lattice.periodicity().toggleAll(true); // Set periodic boundaries.

    defineInitialDensityAtCenter(lattice);

    // First part: loop over time iterations.
    for (plint iT=0; iT<maxIter; ++iT) {
        lattice.collideAndStream();
    }

    // Second part: Data analysis.
    Array<T,2> velocity;
    lattice.get(nx/2, ny/2).computeVelocity(velocity);
    pcout << "Velocity in the middle of the lattice: ("
          << velocity[0] << "," << velocity[1] << ")" << endl;

    pcout << "Velocity norm along a horizontal line: " << endl;
    Box2D line(0, 100, ny/2, ny/2);
    pcout << setprecision(3) << *computeVelocityNorm(*extractSubDomain(lattice, line)) << endl;

    plb_ofstream ofile("profile.dat");
    ofile << setprecision(3) << *computeVelocityNorm(*extractSubDomain(lattice, line)) << endl;

    pcout << "Average density in the domain: " << computeAverageDensity(lattice) << endl;
    pcout << "Average energy in the domain: " << computeAverageEnergy(lattice) << endl;
}
int main(int argc, char* argv[]) {
    plbInit(&argc, &argv);

    global::directories().setOutputDir("./tmp/");
    PlbT Re(600.,600*1e-3);
	pcout << Re.real() <<"  "<<Re.imaginary()<<endl;
	IncomprFlowParam<PlbT> parameters(
            (PlbT) 1e-2,  // uMax
            (PlbT) Re,  // Re
            100,       // N
            6.,        // lx
            1.         // ly 
    );
    const T logT     = (T)0.02;
    const T imSave   = (T)0.06;
    const T vtkSave  = (T)0.06;
    const T maxT     = (T)20.1;
	pcout<<"  " << parameters.getDeltaT().imaginary()<<endl;

    //writeLogFile(parameters, "Poiseuille flow");

    MultiBlockLattice2D<PlbT, DESCRIPTOR> lattice (
            parameters.getNx(), parameters.getNy(),
            new BGKdynamics<PlbT,DESCRIPTOR>(parameters.getOmega()) );
	pcout << parameters.getOmega().real()<<"   "<< parameters.getOmega().imaginary()<< endl;

	

    OnLatticeBoundaryCondition2D<PlbT,DESCRIPTOR>*
        boundaryCondition = createLocalBoundaryCondition2D<PlbT,DESCRIPTOR>();

    cylinderSetup(lattice, parameters, *boundaryCondition);
	
	//Array<PlbT,2> velocity;
//    lattice.get(10, 10).computeVelocity(velocity);
//    pcout << "Velocity in the middle of the lattice: ("
//	<< velocity[0].real()<<" "<<velocity[0].imaginary() << "," << velocity[1].real()<<" "<<velocity[1].imaginary()  << ")" << endl;

    // Main loop over time iterations.
    for (plint iT=0; (T)iT*parameters.getDeltaT().real()<maxT; ++iT) {
        // At this point, the state of the lattice corresponds to the
        //   discrete time iT. However, the stored averages (getStoredAverageEnergy
        //   and getStoredAverageDensity) correspond to the previous time iT-1.

       if (iT%parameters.nStep(imSave)==0) {
            //pcout << "Saving Gif ..." << endl;
            //writeGif(lattice, iT);
        }

        //if (iT%parameters.nStep(vtkSave)==0 && iT>=0) {
        //    pcout << "Saving VTK file ..." << endl;
        //    writeVTK(lattice, parameters, iT);
        //}
		if (iT%parameters.nStep(vtkSave)==0 && iT>=0) {
            pcout << "Saving VTK file ..." << endl;
            writeVTK(lattice, parameters, iT);
			Array<PlbT,2> velocity;
		    lattice.get(10, 10).computeVelocity(velocity);
			pcout << "Velocity in the middle of the lattice: ("
			      << velocity[0].real()<<" "<<velocity[0].imaginary() << "," << velocity[1].real()<<" "<<velocity[1].imaginary()  << ")" << endl;
        }

        if (iT%parameters.nStep(logT)==0) {
            pcout << "step " << iT
                  << "; t=" << (T)iT*parameters.getDeltaT().real();
        }

        // Lattice Boltzmann iteration step.
        lattice.collideAndStream();
//		lattice.get(10, 10).computeVelocity(velocity);
//		pcout << "Velocity in the middle of the lattice: ("
//		<< velocity[0].real()<<" "<<velocity[0].imaginary() << "," << velocity[1].real()<<" "<<velocity[1].imaginary()  << ")" << endl;

        // At this point, the state of the lattice corresponds to the
        //   discrete time iT+1, and the stored averages are upgraded to time iT.
        if (iT%parameters.nStep(logT)==0) {
            pcout << "; av energy ="
                  << setprecision(10) << getStoredAverageEnergy<PlbT>(lattice)
                  << "; av rho ="
                  << getStoredAverageDensity<PlbT>(lattice) << endl;
        }
    }
    
    delete boundaryCondition;
}