Blender V2.61 - r43446
|
00001 00004 /****************************************************************************** 00005 * 00006 * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method 00007 * Copyright 2003-2006 Nils Thuerey 00008 * 00009 * Global C style utility funcions 00010 * 00011 *****************************************************************************/ 00012 00013 00014 #include <iostream> 00015 #include <sstream> 00016 #ifdef WIN32 00017 // for timing 00018 #include <windows.h> 00019 #else 00020 #include <time.h> 00021 #include <sys/time.h> 00022 #include <sys/times.h> 00023 #endif 00024 00025 #include "utilities.h" 00026 00027 #ifndef NOPNG 00028 #ifdef WIN32 00029 #include "png.h" 00030 #else 00031 #include <png.h> 00032 #endif 00033 #endif // NOPNG 00034 #include <zlib.h> 00035 00036 // global debug level 00037 #ifdef DEBUG 00038 int gDebugLevel = DEBUG; 00039 #else // DEBUG 00040 int gDebugLevel = 0; 00041 #endif // DEBUG 00042 00043 // global world state, acces with get/setElbeemState 00044 int gElbeemState = SIMWORLD_INVALID; 00045 00046 // access global state of elbeem simulator 00047 void setElbeemState(int set) { 00048 gElbeemState = set; 00049 } 00050 int getElbeemState(void) { 00051 return gElbeemState; 00052 } 00053 int isSimworldOk(void) { 00054 return (getElbeemState>=0); 00055 } 00056 00057 // last error as string, acces with get/setElbeemErrorString 00058 char gElbeemErrorString[256] = {'-','\0' }; 00059 00060 // access elbeem simulator error string 00061 void setElbeemErrorString(const char* set) { 00062 strncpy(gElbeemErrorString, set, 256); 00063 } 00064 char* getElbeemErrorString(void) { return gElbeemErrorString; } 00065 00066 00068 myTime_t globalIntervalTime = 0; 00070 #ifdef WIN32 00071 // switch off first call 00072 #define DEF_globalColorSetting -1 00073 #else // WIN32 00074 // linux etc., on by default 00075 #define DEF_globalColorSetting 1 00076 #endif // WIN32 00077 int globalColorSetting = DEF_globalColorSetting; // linux etc., on by default 00078 int globalFirstEnvCheck = 0; 00079 void resetGlobalColorSetting() { globalColorSetting = DEF_globalColorSetting; } 00080 00081 // global string for formatting vector output, TODO test!? 00082 const char *globVecFormatStr = "V[%f,%f,%f]"; 00083 00084 00085 // global mp on/off switch 00086 bool glob_mpactive = false; 00087 // global access to mpi index, for debugging (e.g. in utilities.cpp) 00088 int glob_mpnum = -1; 00089 int glob_mpindex = -1; 00090 int glob_mppn = -1; 00091 00092 00093 //----------------------------------------------------------------------------- 00094 // helper function that converts a string to integer, 00095 // and returns an alternative value if the conversion fails 00096 int convertString2Int(const char *str, int alt) 00097 { 00098 int val; 00099 char *endptr; 00100 bool success=true; 00101 00102 val = strtol(str, &endptr, 10); 00103 if( (str==endptr) || 00104 ((str!=endptr) && (*endptr != '\0')) ) success = false; 00105 00106 if(!success) { 00107 return alt; 00108 } 00109 return val; 00110 } 00111 00112 //----------------------------------------------------------------------------- 00114 string convertFlags2String(int flags) { 00115 std::ostringstream ret; 00116 ret <<"("; 00117 int max = sizeof(int)*8; 00118 for(int i=0; i<max; i++) { 00119 if(flags & (1<<31)) ret <<"1"; 00120 else ret<<"0"; 00121 if(i<max-1) { 00122 //ret << ","; 00123 if((i%8)==7) ret << " "; 00124 } 00125 flags = flags << 1; 00126 } 00127 ret <<")"; 00128 return ret.str(); 00129 } 00130 00131 #ifndef NOPNG 00132 //----------------------------------------------------------------------------- 00134 int writePng(const char *fileName, unsigned char **rowsp, int w, int h) 00135 { 00136 // defaults for elbeem 00137 const int colortype = PNG_COLOR_TYPE_RGBA; 00138 const int bitdepth = 8; 00139 png_structp png_ptr = NULL; 00140 png_infop info_ptr = NULL; 00141 png_bytep *rows = rowsp; 00142 00143 //FILE *fp = fopen(fileName, "wb"); 00144 FILE *fp = NULL; 00145 string doing = "open for writing"; 00146 if (!(fp = fopen(fileName, "wb"))) goto fail; 00147 00148 if(!png_ptr) { 00149 doing = "create png write struct"; 00150 if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) goto fail; 00151 } 00152 if(!info_ptr) { 00153 doing = "create png info struct"; 00154 if (!(info_ptr = png_create_info_struct(png_ptr))) goto fail; 00155 } 00156 00157 if (setjmp(png_jmpbuf(png_ptr))) goto fail; 00158 doing = "init IO"; 00159 png_init_io(png_ptr, fp); 00160 doing = "write header"; 00161 png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, colortype, PNG_INTERLACE_NONE, 00162 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 00163 doing = "write info"; 00164 png_write_info(png_ptr, info_ptr); 00165 doing = "write image"; 00166 png_write_image(png_ptr, rows); 00167 doing = "write end"; 00168 png_write_end(png_ptr, NULL); 00169 doing = "write destroy structs"; 00170 png_destroy_write_struct(&png_ptr, &info_ptr); 00171 00172 fclose( fp ); 00173 return 0; 00174 00175 fail: 00176 errMsg("writePng","Write_png: could not "<<doing<<" !"); 00177 if(fp) fclose( fp ); 00178 if(png_ptr || info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr); 00179 return -1; 00180 } 00181 #else // NOPNG 00182 // fallback - write ppm 00183 int writePng(const char *fileName, unsigned char **rowsp, int w, int h) 00184 { 00185 gzFile gzf; 00186 string filentemp(fileName); 00187 // remove suffix 00188 if((filentemp.length()>4) && (filentemp[filentemp.length()-4]=='.')) { 00189 filentemp[filentemp.length()-4] = '\0'; 00190 } 00191 std::ostringstream filennew; 00192 filennew << filentemp.c_str(); 00193 filennew << ".ppm.gz"; 00194 00195 gzf = gzopen(filennew.str().c_str(), "wb9"); 00196 if(!gzf) goto fail; 00197 00198 gzprintf(gzf,"P6\n%d %d\n255\n",w,h); 00199 // output binary pixels 00200 for(int j=0;j<h;j++) { 00201 for(int i=0;i<h;i++) { 00202 // remove alpha values 00203 gzwrite(gzf,&rowsp[j][i*4],3); 00204 } 00205 } 00206 00207 gzclose( gzf ); 00208 errMsg("writePng/ppm","Write_png/ppm: wrote to "<<filennew.str()<<"."); 00209 return 0; 00210 00211 fail: 00212 errMsg("writePng/ppm","Write_png/ppm: could not write to "<<filennew.str()<<" !"); 00213 return -1; 00214 } 00215 #endif // NOPNG 00216 00217 00218 //----------------------------------------------------------------------------- 00219 // helper function to determine current time 00220 myTime_t getTime() 00221 { 00222 myTime_t ret = 0; 00223 #ifdef WIN32 00224 LARGE_INTEGER liTimerFrequency; 00225 QueryPerformanceFrequency(&liTimerFrequency); 00226 LARGE_INTEGER liLastTime; 00227 QueryPerformanceCounter(&liLastTime); 00228 ret = (INT)( ((double)liLastTime.QuadPart / liTimerFrequency.QuadPart)*1000 ); // - mFirstTime; 00229 #else 00230 struct timeval tv; 00231 struct timezone tz; 00232 tz.tz_minuteswest = 0; 00233 tz.tz_dsttime = 0; 00234 gettimeofday(&tv,&tz); 00235 ret = (tv.tv_sec*1000)+(tv.tv_usec/1000); //-mFirstTime; 00236 #endif 00237 return (myTime_t)ret; 00238 } 00239 //----------------------------------------------------------------------------- 00240 // convert time to readable string 00241 string getTimeString(myTime_t usecs) { 00242 std::ostringstream ret; 00243 //myTime_t us = usecs % 1000; 00244 myTime_t ms = (myTime_t)( (double)usecs / (60.0*1000.0) ); 00245 myTime_t ss = (myTime_t)( ((double)usecs / 1000.0) - ((double)ms*60.0) ); 00246 int ps = (int)( ((double)usecs - (double)ss*1000.0)/10.0 ); 00247 00248 //ret.setf(ios::showpoint|ios::fixed); 00249 //ret.precision(5); ret.width(7); 00250 00251 if(ms>0) { 00252 ret << ms<<"m"<< ss<<"s" ; 00253 } else { 00254 if(ps>0) { 00255 ret << ss<<"."; 00256 if(ps<10) { ret <<"0"; } 00257 ret <<ps<<"s" ; 00258 } else { 00259 ret << ss<<"s" ; 00260 } 00261 } 00262 return ret.str(); 00263 } 00264 00266 bool checkBoundingBox(ntlVec3Gfx s, ntlVec3Gfx e, string checker) { 00267 if( (s[0]>e[0]) || 00268 (s[1]>e[1]) || 00269 (s[2]>e[2]) ) { 00270 errFatal("checkBoundingBox","Check by '"<<checker<<"' for BB "<<s<<":"<<e<<" failed! Aborting...",SIMWORLD_INITERROR); 00271 return 1; 00272 } 00273 return 0; 00274 } 00275 00276 00277 00278 //----------------------------------------------------------------------------- 00279 // debug message output 00280 00281 static string col_black ( "\033[0;30m"); 00282 static string col_dark_gray ( "\033[1;30m"); 00283 static string col_bright_gray ( "\033[0;37m"); 00284 static string col_red ( "\033[0;31m"); 00285 static string col_bright_red ( "\033[1;31m"); 00286 static string col_green ( "\033[0;32m"); 00287 static string col_bright_green ( "\033[1;32m"); 00288 static string col_bright_yellow ( "\033[1;33m"); 00289 static string col_yellow ( "\033[0;33m"); 00290 static string col_cyan ( "\033[0;36m"); 00291 static string col_bright_cyan ( "\033[1;36m"); 00292 static string col_purple ( "\033[0;35m"); 00293 static string col_bright_purple ( "\033[1;35m"); 00294 static string col_neutral ( "\033[0m"); 00295 static string col_std = col_bright_gray; 00296 00297 std::ostringstream globOutstr; 00298 bool globOutstrForce=false; 00299 #define DM_NONE 100 00300 void messageOutputForce(string from) { 00301 bool org = globOutstrForce; 00302 globOutstrForce = true; 00303 messageOutputFunc(from, DM_NONE, "\n", 0); 00304 globOutstrForce = org; 00305 } 00306 00307 void messageOutputFunc(string from, int id, string msg, myTime_t interval) { 00308 // fast skip 00309 if((id!=DM_FATAL)&&(gDebugLevel<=0)) return; 00310 00311 if(interval>0) { 00312 myTime_t currTime = getTime(); 00313 if((currTime - globalIntervalTime)>interval) { 00314 globalIntervalTime = getTime(); 00315 } else { 00316 return; 00317 } 00318 } 00319 00320 // colors off? 00321 if( (globalColorSetting == -1) || // off for e.g. win32 00322 ((globalColorSetting==1) && ((id==DM_FATAL)||( getenv("ELBEEM_NOCOLOROUT") )) ) 00323 ) { 00324 // only reset once 00325 col_std = col_black = col_dark_gray = col_bright_gray = 00326 col_red = col_bright_red = col_green = 00327 col_bright_green = col_bright_yellow = 00328 col_yellow = col_cyan = col_bright_cyan = 00329 col_purple = col_bright_purple = col_neutral = ""; 00330 globalColorSetting = 0; 00331 } 00332 00333 std::ostringstream sout; 00334 if(id==DM_DIRECT) { 00335 sout << msg; 00336 } else { 00337 sout << col_cyan<< from; 00338 switch(id) { 00339 case DM_MSG: 00340 sout << col_std << " message:"; 00341 break; 00342 case DM_NOTIFY: 00343 sout << col_bright_cyan << " note:" << col_std; 00344 break; 00345 case DM_IMPORTANT: 00346 sout << col_yellow << " important:" << col_std; 00347 break; 00348 case DM_WARNING: 00349 sout << col_bright_red << " warning:" << col_std; 00350 break; 00351 case DM_ERROR: 00352 sout << col_red << " error:" << col_red; 00353 break; 00354 case DM_FATAL: 00355 sout << col_red << " fatal("<<gElbeemState<<"):" << col_red; 00356 break; 00357 case DM_NONE: 00358 // only internal debugging msgs 00359 break; 00360 default: 00361 // this shouldnt happen... 00362 sout << col_red << " --- messageOutputFunc error: invalid id ("<<id<<") --- aborting... \n\n" << col_std; 00363 break; 00364 } 00365 sout <<" "<< msg << col_std; 00366 } 00367 00368 if(id==DM_FATAL) { 00369 strncpy(gElbeemErrorString,sout.str().c_str(), 256); 00370 // dont print? 00371 if(gDebugLevel==0) return; 00372 sout << "\n"; // add newline for output 00373 } 00374 00375 // determine output - file==1/stdout==0 / globstr==2 00376 char filen[256]; 00377 strcpy(filen,"debug_unini.txt"); 00378 int fileout = false; 00379 #if ELBEEM_MPI==1 00380 std::ostringstream mpin; 00381 if(glob_mpindex>=0) { 00382 mpin << "elbeem_log_"<< glob_mpindex <<".txt"; 00383 } else { 00384 mpin << "elbeem_log_ini.txt"; 00385 } 00386 fileout = 1; 00387 strncpy(filen, mpin.str().c_str(),255); filen[255]='\0'; 00388 #else 00389 strncpy(filen, "elbeem_debug_log.txt",255); 00390 #endif 00391 00392 #ifdef WIN32 00393 // windows causes trouble with direct output 00394 fileout = 1; 00395 #endif // WIN32 00396 00397 #if PARALLEL==1 00398 fileout = 2;// buffer out, switch off again... 00399 if(globOutstrForce) fileout=1; 00400 #endif 00401 if(getenv("ELBEEM_FORCESTDOUT")) { 00402 fileout = 0;// always direct out 00403 } 00404 //fprintf(stdout,"out deb %d, %d, '%s',l%d \n",globOutstrForce,fileout, filen, globOutstr.str().size() ); 00405 00406 #if PARALLEL==1 00407 #pragma omp critical 00408 #endif // PARALLEL==1 00409 { 00410 if(fileout==1) { 00411 // debug level is >0 anyway, so write to file... 00412 FILE *logf = fopen(filen,"a+"); 00413 // dont complain anymore here... 00414 if(logf) { 00415 if(globOutstrForce) { 00416 fprintf(logf, "%s",globOutstr.str().c_str() ); 00417 globOutstr.str(""); // reset 00418 } 00419 fprintf(logf, "%s",sout.str().c_str() ); 00420 fclose(logf); 00421 } 00422 } else if(fileout==2) { 00423 globOutstr << sout.str(); 00424 } else { 00425 // normal stdout output 00426 fprintf(stdout, "%s",sout.str().c_str() ); 00427 if(id!=DM_DIRECT) fflush(stdout); 00428 } 00429 } // omp crit 00430 } 00431 00432 // helper functions from external program using elbeem lib (e.g. Blender) 00433 /* set gDebugLevel according to env. var */ 00434 extern "C" 00435 void elbeemCheckDebugEnv(void) { 00436 const char *strEnvName = "BLENDER_ELBEEMDEBUG"; 00437 const char *strEnvName2 = "ELBEEM_DEBUGLEVEL"; 00438 if(globalFirstEnvCheck) return; 00439 00440 if(getenv(strEnvName)) { 00441 gDebugLevel = atoi(getenv(strEnvName)); 00442 if(gDebugLevel>0) debMsgStd("performElbeemSimulation",DM_NOTIFY,"Using envvar '"<<strEnvName<<"'='"<<getenv(strEnvName)<<"', debugLevel set to: "<<gDebugLevel<<"\n", 1); 00443 } 00444 if(getenv(strEnvName2)) { 00445 gDebugLevel = atoi(getenv(strEnvName2)); 00446 if(gDebugLevel>0) debMsgStd("performElbeemSimulation",DM_NOTIFY,"Using envvar '"<<strEnvName2<<"'='"<<getenv(strEnvName2)<<"', debugLevel set to: "<<gDebugLevel<<"\n", 1); 00447 } 00448 if(gDebugLevel< 0) gDebugLevel = 0; 00449 if(gDebugLevel>10) gDebugLevel = 0; // only use valid values 00450 globalFirstEnvCheck = 1; 00451 } 00452 00453 /* elbeem debug output function */ 00454 extern "C" 00455 void elbeemDebugOut(char *msg) { 00456 elbeemCheckDebugEnv(); 00457 // external messages default to debug level 5... 00458 if(gDebugLevel<5) return; 00459 // delegate to messageOutputFunc 00460 messageOutputFunc("[External]",DM_MSG,msg,0); 00461 } 00462 00463 /* set elbeem debug output level (0=off to 10=full on) */ 00464 extern "C" 00465 void elbeemSetDebugLevel(int level) { 00466 if(level<0) level=0; 00467 if(level>10) level=10; 00468 gDebugLevel=level; 00469 } 00470 00471 00472 /* estimate how much memory a given setup will require */ 00473 #include "solver_interface.h" 00474 00475 extern "C" 00476 double elbeemEstimateMemreq(int res, 00477 float sx, float sy, float sz, 00478 int refine, char *retstr) { 00479 int resx = res, resy = res, resz = res; 00480 // dont use real coords, just place from 0.0 to sizeXYZ 00481 ntlVec3Gfx vgs(0.0), vge(sx,sy,sz); 00482 initGridSizes( resx,resy,resz, vgs,vge, refine, 0); 00483 00484 double memreq = -1.0; 00485 string memreqStr(""); 00486 // ignore farfield for now... 00487 calculateMemreqEstimate(resx,resy,resz, refine, 0., &memreq, NULL, &memreqStr ); 00488 00489 if(retstr) { 00490 // copy at max. 32 characters 00491 strncpy(retstr, memreqStr.c_str(), 32 ); 00492 retstr[31] = '\0'; 00493 } 00494 return memreq; 00495 } 00496 00497 00498