Fluid Dynamics Library
vlmain.cpp
00001 
00027 #include <boost/program_options.hpp>
00028 #include <boost/thread.hpp>
00029 #include <boost/signal.hpp>
00030 #include <boost/bind.hpp>
00031 #include <boost/format.hpp>
00032 namespace po = boost::program_options;
00033 
00034 #include <vlCore/VisualizationLibrary.hpp>
00035 #include <vlGLUT/GLUTWindow.hpp>
00036 #include <vlCore/VLSettings.hpp>
00037 
00038 #include "logger/logger.h"
00039 #include "logger/stdiowriter.h"
00040 #include "logger/syslogwriter.h"
00041 
00042 #include "core/common.h"
00043 #include "core/fields.hpp"
00044 #include "core/scalars.hpp"
00045 #include "core/macsmoke.hpp"
00046 #include "core/inssmoke.hpp"
00047 #include "core/pointrender.hpp"
00048 #include "core/volumerender.hpp"
00049 #include "render/glutapp.h"
00050 #include "render/drawable.h"
00051 #include "io/xmlparser.h"
00052 
00053 #ifndef TARGET_VERSION_MAJOR
00054 #define TARGET_VERSION_MAJOR 99
00055 #endif
00056 
00057 #ifndef TARGET_VERSION_MINOR
00058 #define TARGET_VERSION_MINOR 99
00059 #endif
00060 
00061 static fdl::MACSmoke<float>* grid = NULL;
00062 static fdl::INSSmoke<float>* solver = NULL;
00063 fdl::Constant<float>* gravityField = NULL;
00064 // static fdl::FieldBase<float>* advectField = NULL;
00065 static fdl::ScalarBase<float>* smokeSrc = NULL;
00066 static fdl::ScalarBase<float>* tempSrc = NULL;
00067 static vl::ref<fdl::VolumeRenderer> applet;
00068 
00072 template<class T>
00073 std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
00074 {
00075         std::copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, " ")); 
00076         return os;
00077 }
00078 
00079 void simulateSmoke()
00080 {
00081         for (int t = 0; t < 200; ++t) {
00082                 
00083                 INFO() << boost::format("T= %g, S= %g, p= %g, u= %g, v= %g, w= %g") \
00084                 % grid->supP() % grid->supT() % grid->supS() % grid->supU() % grid->supV() % grid->supW();
00085                 
00086                 INFO() << "Advection step";
00087                 solver->advect();
00088                 
00089                 INFO() << "Adding external force";
00090                 solver->addfield();
00091                 
00092                 INFO() << "Adding source terms";
00093                 solver->addsources();
00094                 
00095                 INFO() << "Pressure update step";
00096                 solver->project();
00097         }
00098 }
00099 
00104 int main(int argc, char **argv)
00105 {
00106         fdl::Logger out;
00107         // figure out how to automate this output...
00108         std::cout << "FDL version " << TARGET_VERSION_MAJOR << "." << TARGET_VERSION_MINOR << " of " << __DATE__ << " at " << __TIME__ << std::endl;
00109         
00110         fdl::SyslogWriter* syslogger = new fdl::SyslogWriter();
00111         fdl::StdOutWriter* stdlogger = new fdl::StdOutWriter();
00112         stdlogger->setFormat("%H:%M:%S");
00113         fdl::Logger::setIdentity("FDL");
00114         // fdl::Logger::RegisterWriter(syslogger);
00115         fdl::Logger::registerWriter(stdlogger);
00116         fdl::Logger::setLevel(fdl::Logger::WARN | fdl::Logger::ERROR);
00117         
00118         std::string output_prefix = "density_export_";
00119         
00120         int window_width, window_height;
00121         int use_glut_window = 1;
00122         std::string render_exporter = "";
00123         std::string levelLabel = "";
00124         std::string inputfile = "";
00125         int level = 0;
00126         
00127         float dx = 0.1;
00128         float dt = 0.1;
00129         float rho = 1.0;
00130         std::vector<int> grid_dims(3, 50);
00131         float solidTemp = 0.0;
00132         float smokeSrcTemp = 2.0;
00133         
00134         float gvec[3] = {0.0, 0.0, -1.0}; // gravitational field (constant)
00135 
00136         float cg_tol = fdl::EPSILON; 
00137         unsigned cg_maxiter = 200;
00138         float ode_tol = 1e-2;
00139         
00140         try {
00141                 po::options_description desc("Allowed options");
00142                 desc.add_options()
00143                 ("help,H", "produce help message")
00144                 ("input-file,C", po::value<std::string>(&inputfile), "input configuration file")
00145                 ("output-format,O", po::value<std::string>(), "output format")
00146                 ("output-name,N", po::value<std::string>(&output_prefix), "output file name PREFIX")
00147                 ("win-width,W", po::value<int>(&window_width)->default_value(512), "Glut window width")
00148                 ("win-height,E", po::value<int>(&window_height)->default_value(512), "Glut window height")
00149                 ("use-glut,L", po::value<int>(&use_glut_window)->default_value(1), "Use Glut rendering window")
00150                 ("verbose,V", po::value<int>(&level), "logging level");
00151                 
00152                 po::variables_map vm;
00153                 po::store(po::command_line_parser(argc, argv).options(desc).style(po::command_line_style::default_style 
00154                         | po::command_line_style::allow_slash_for_short 
00155                         | po::command_line_style::allow_long_disguise).run(), vm);
00156                 
00157                 po::notify(vm);
00158                 
00159                 if (vm.count("help")) {
00160                         std::cout << "Usage: options_description [options]" << std::endl;
00161                         std::cout << desc << std::endl;
00162                         return 0;
00163                 }
00164                 
00165                 if (vm.count("output-name")) {
00166                         std::cout << "Output name is: " << vm["output-name"].as<std::string>() << std::endl;
00167                 }
00168                 
00169                 if (vm.count("output-format")) {
00170                         std::cout << "Output format is: " << vm["output-format"].as<std::string>() << std::endl;
00171                 }
00172                 
00173                 if(level >= 0){
00174                         levelLabel = fdl::Logger::loggerLevelAsString(fdl::Logger::INFO);
00175                         fdl::Logger::pushLevel(fdl::Logger::INFO);
00176                 }
00177                 if(level >= 1){
00178                         levelLabel = fdl::Logger::loggerLevelAsString(fdl::Logger::DEV);
00179                         fdl::Logger::pushLevel(fdl::Logger::DEV);
00180                 }
00181                 if(level >= 2){
00182                         levelLabel = fdl::Logger::loggerLevelAsString(fdl::Logger::DEBUG);
00183                         fdl::Logger::pushLevel(fdl::Logger::DEBUG);
00184                 }
00185                                 
00186                 if (vm.count("renderer")) {
00187                         std::cout << "Output name is: " << vm["output-name"].as<std::string>() << std::endl;
00188                 }
00189 
00190                 gravityField = new fdl::Constant<float>(3, gvec);
00191 
00192                 float x_rel = 0.5, y_rel = 0.5;
00193                 float sph_R0[3] = {grid_dims[0] * dx * x_rel, grid_dims[1] * dx * y_rel, dx};
00194                 float sph_r = dx * 3;
00195 
00196                 float cyl_XY[2] = {grid_dims[0] * dx * x_rel, grid_dims[1] * dx * y_rel};
00197                 float cyl_z[2] = {dx, 3 * dx};
00198                 float cyl_r = dx * 4;
00199 
00200                 smokeSrc = new fdl::Cylindrical<float>(3, cyl_XY, cyl_r, cyl_z[0], cyl_z[1], 0.1 );
00201                 tempSrc = new fdl::Gaussian<float>(3, sph_R0, sph_r, smokeSrcTemp);
00202 
00203                 grid = new fdl::MACSmoke<float>(grid_dims[0], grid_dims[1], grid_dims[2], dx, solidTemp);
00204                 // solver = new fdl::INSSmoke<float>(grid, gravityField, rho, dt, tempScalar, smokeSrc);
00205                 
00206                 
00207                 INFO() << "Initializing for fluid at rest in solid container ";
00208                 
00209                 float X_tmp[3];
00210                 for (int x = 1; x <= grid->xdim(); ++x) {
00211                         for (int y = 1; y <= grid->ydim(); ++y) {
00212                                 for (int z = 1; z <= grid->zdim(); ++z) 
00213                                 {
00214                                         // at the boundary...
00215                                         if (x == 1 || x == grid->xdim() ||
00216                                                  y == 1 || y == grid->ydim() ||
00217                                                  z == 1 || z == grid->zdim())
00218                                         {
00219                                                 grid->operator()(x, y, z) = fdl::SOLID;
00220                                                 grid->p(x, y, z) = 0.0;
00221                                                 grid->u(x, y, z) = 0.0;
00222                                                 grid->u(x+1, y, z) = 0.0;
00223                                                 grid->v(x, y, z) = 0.0;
00224                                                 grid->v(x, y+1, z) = 0.0;
00225                                                 grid->w(x, y, z) = 0.0;
00226                                                 grid->w(x, y, z+1) = 0.0;
00227                                                 grid->T(x, y, z) = 1.0; // this is a hack
00228                                                 grid->s(x, y, z) = 0.0;
00229                                         } else {
00230                                                 grid->operator()(x, y, z) = fdl::FLUID;
00231                                                 grid->p(x, y, z) = 1.0;
00232                                                 grid->u(x, y, z) = 0.0;
00233                                                 grid->v(x, y, z) = 0.0;
00234                                                 grid->w(x, y, z) = 0.0;
00235                                                 grid->coordsP(x, y, z, X_tmp);
00236                                                 grid->T(x, y, z) = (*tempSrc)(0.0, X_tmp);
00237                                                 // grid->T(x, y, z) = 0.0;
00238                                                 grid->s(x, y, z) = (*smokeSrc)(0.0, X_tmp);
00239                                         }
00240                                 }
00241                         }
00242                 }
00243                 
00244                 solver = new fdl::INSSmoke<float>(grid, gravityField, rho, dt, tempSrc, smokeSrc);
00245                 solver->setStepTolerance(ode_tol);
00246                 solver->setStepRule(fdl::RK2);
00247                 
00248                 INFO() << "Logging level is " << levelLabel << " (" << level << ")";
00249                 INFO() << "Grid dimensions are: " << grid->xdim() << " x " << grid->ydim() << " x " << grid->zdim();
00250                 INFO() << "Cell width is: " << grid->dx();
00251                 INFO() << "Time step is:  " << solver->dt();
00252                 INFO() << "CG solver tolerance is: " << solver->getCGTolerance();
00253                 INFO() << "CG solver max iterations is: " << solver->getCGMaxIter();
00254                 INFO() << "Fluid density coeff. is:  " << solver->rho();
00255                 
00256                 if(use_glut_window>0){
00257                         boost::thread t(simulateSmoke);
00258                         
00259                         int pargc = argc;
00260                         glutInit( &pargc, argv );
00261                 
00262                         // init Visualization Library
00263                         vl::VisualizationLibrary::init();
00264                         vl::globalSettings()->setDataPath(vl::String("."));
00265                 
00266                         // setup the OpenGL context format
00267                         vl::OpenGLContextFormat format;
00268                         format.setDoubleBuffer(true);
00269                         format.setRGBABits( 8,8,8,8 );
00270                         format.setDepthBufferBits(24);
00271                         format.setStencilBufferBits(8);
00272                         format.setFullscreen(false);
00273                         format.setMultisampleSamples(8);
00274                         format.setMultisample(true);
00275                                         
00276                         // create the applet to be run
00277                         //applet = new fdl::PointRenderer();
00278                         applet = new fdl::VolumeRenderer();
00279                         applet->initialize();
00280                         applet->setGrid(grid);
00281                         //applet->setSolver(solver);
00282                         // create a native GLUT window
00283                         vl::ref<vlGLUT::GLUTWindow> glut_window = new vlGLUT::GLUTWindow;
00284                         // bind the applet so it receives all the GUI events related to the OpenGLContext
00285                         glut_window->addEventListener(applet.get());            
00286                         // target the window so we can render on it
00287                         applet->rendering()->as<Rendering>()->renderer()->setRenderTarget( glut_window->renderTarget() );
00288                         // black background
00289                         applet->rendering()->as<Rendering>()->camera()->viewport()->setClearColor( vl::black );
00290                         // define the camera position and orientation
00291                         vl::vec3 eye    = vl::vec3(0,30,0);     // camera position
00292                         vl::vec3 target = vl::vec3(0,0,0);      // point the camera is looking at
00293                         vl::vec3 up     = vl::vec3(0,1,0);      // up direction
00294                         
00295                         // --- trackball manipulator ---
00296                         vl::ref<vl::TrackballManipulator> trackball = new vl::TrackballManipulator;
00297                         // bind the camera to be manipulated
00298                         trackball->setCamera( applet->rendering()->as<Rendering>()->camera() );
00299                         // manipulate the camera's transform
00300                         trackball->setTransform(NULL);
00301                         // rotation pivot coordinates
00302                         trackball->setPivot( vl::vec3(0,0,0) );
00303                         // install the trackball
00304                         glut_window->addEventListener(trackball.get());
00305                         
00306                         AABB volume_box( vec3( 0,0,0 ), vec3( 1,1,1 ) );
00307                         trackball->adjustView(volume_box, vl::vec3(10,10,10), up);
00308                 
00309                         // Initialize the OpenGL context and window properties
00310                         glut_window->initGLUTWindow( "FDL", format, 0, 0, window_width, window_height );
00311                 
00312                         glutMainLoop();
00313                 }
00314                 else{
00315                         simulateSmoke();
00316                 }
00317                 
00318         }
00319         catch(std::exception& e) {
00320                 ERROR() << " * error: " << e.what();
00321                 return 1;
00322         }
00323         catch(...) {
00324                 ERROR() << "Exception of unknown type!";
00325         }
00326         
00327         /* 
00328          Idea: move this stuff into the class constructors 
00329         
00330         std::cout << "Grid dimensions are: " << grid_dims[0] << " x " << grid_dims[1] << " x " << grid_dims[2] << std::endl;
00331         std::cout << "Cell width is: " << dx << std::endl;
00332         // and so on...
00333          */
00334         
00335         delete solver;
00336         delete grid;
00337                 
00338         return 0;
00339 }