; ; create-movie.scm ; ; This file can be executed by Fluent before a simulation by running ; (load "create-movie.scm") ; as a text command. It will setup a hook for every timestep, so images can ; be saved. After simulation, you can finish the movie with ; (movie-finish) ; ; Before you (load "...") this file, it's advisable to set the output movie ; (define outputmovie "/foo/bar/output.avi") ; Optionally, you can define the temporary file dir ; (define tmpmoviedir "/tmp/foobar") ; and how often a frame should be saved ; (define frame_every 5) ; ; PORTABILITY NOTES ; - Make sure you point tmpmoviedir to a valid directory ; - Look for (system "xxx") commands and adapt to your platform. ; E.g. on windows, "del" is used to remove files instead of "rm", so change ; (system (format #f "rm -f ~a/*" tmpmoviedir)) ; to ; (system (format #f "del ~a\*.*" tmpmoviedir)) ; - The following external programs are used: ; convert - ImageMagick ( http://imagemagick.org/ ) for image operations ; ffmpeg - ffmpeg ( http://ffmpeg.sourceforge.net/ ) for movie encoding ; (if (not (symbol-bound? 'outputmovie (the-environment))) (define outputmovie "movie.avi")) ;; output movie (if (not (symbol-bound? 'tmpmoviedir (the-environment))) (define tmpmoviedir "/tmp/fluent-wrk")) ;; where to temporarily save images (if (not (symbol-bound? 'frame_every (the-environment))) (define frame_every (/ 0.05 (rpgetvar 'time-step)))) ;; how many time steps per frame: 20 frames/s ;; Default function to display a time step (if (not (symbol-bound? 'disp (the-environment))) (define (disp) (and (ti-menu-load-string "/display/set/line-weight 1") (ti-menu-load-string "/display/set/render-grid n") (ti-menu-load-string "/display/set/contours/filled-contours y") (ti-menu-load-string "/display/set/contours/n-contour 60") (ti-menu-load-string "/display/set/global-range y") (ti-menu-load-string "/display/set/contours/clip-to-range y") ; (ti-menu-load-string "/display/contour mixture pressure ,,") (ti-menu-load-string "/display/set/contours/node-values n") (ti-menu-load-string "/display/contour mixture velocity ,,") (ti-menu-load-string "/display/re-scale 0 25") ; (ti-menu-load-string "/display/re-scale -5000 5000") ;; pressure absolute scale -0.05 - +0.05 [10^5 Pa] ;; (ti-menu-load-string "/display/contour phase-1 vof ,,") ;; (ti-menu-load-string "/display/set/render-grid n") ;; (ti-menu-load-string "/display/set/overlays n") ;; (ti-menu-load-string "/display/set/line-weight 1") ;; (ti-menu-load-string "/display/contour mixture pressure ,,") ;; (ti-menu-load-string "/display/set/overlays y") ;; (ti-menu-load-string "/display/grid") ;; (ti-menu-load-string "/display/set/line-weight 5") ;; (ti-menu-load-string "/display/set/contours/filled-contours n") ;; (ti-menu-load-string "/display/set/contours/n-contour 2") ;; (ti-menu-load-string "/display/contour phase-1 vof ,,") ) ) ) ;; Display phase boundary (define (disp-phase-boundary) (and (ti-menu-load-string "/display/set/render-grid n") (ti-menu-load-string "/display/set/line-weight 2") (ti-menu-load-string "/display/set/contours/filled-contours n") (ti-menu-load-string "/display/set/contours/n-contour 2") (ti-menu-load-string "/display/contour phase-1 vof ,,") ) ) ;; Function to call at every time step (define (disp-save) (and ;; Store image (let ((seq_num (/ (rpgetvar 'time-step) frame_every))) (let ( ;; Interim files (imgfileA (format #f "~a/movie-~04d-A.ppm" tmpmoviedir seq_num)) (imgfileB (format #f "~a/movie-~04d-B.ppm" tmpmoviedir seq_num)) (imgfileC (format #f "~a/movie-~04d-C.png" tmpmoviedir seq_num)) (imgfileD (format #f "~a/movie-~04d-D.png" tmpmoviedir seq_num)) ;; Final image (imgfileZ (format #f "~a/movie-~04d.jpg" tmpmoviedir seq_num)) ) (system (format #f "rm -f ~a ~a ~a ~a ~a" imgfileA imgfileB imgfileC imgfileD imgfileZ)) ;; Contour diagram (disp) (ti-menu-load-string (format #f "/display/hardcopy ~a" imgfileA)) ;; Overlay phase boundary (disp-phase-boundary) (ti-menu-load-string (format #f "/display/hardcopy ~a" imgfileB)) ; ---> Modify this when changing window size! ; 168 is width in pixels of color bar at left ; 85 is height in pixels of bottom comment block (system (format #f "convert ~a -transparent white -gravity South -chop 0x85 ~a" imgfileB imgfileC)) (system (format #f "convert ~a -gravity West -chop 168x0 ~a" imgfileC imgfileD)) ; end of window size modification <--- (system (format #f "convert ~a ~a -gravity NorthEast -composite ~a" imgfileA imgfileD imgfileZ)) ;; Remove interim files (system (format #f "rm -f ~a ~a ~a ~a" imgfileA imgfileB imgfileC imgfileD)) (display (format #f "Stored image ~a" imgfileZ)) )) ) ) ;; Function to create movie from data files (define (movie-initialize) ;; Setup temp dir (system (format #f "mkdir -p ~a" tmpmoviedir)) (system (format #f "rm -f ~a/*" tmpmoviedir)) ;; Set image format (ti-menu-load-string "display/set/hardcopy/driver/ppm") (ti-menu-load-string "display/set/hardcopy/color-mode/color") ) ;; Hook movie into gui ;; XXX very bad implementation (define (movie-hook) (cx-gui-do cx-activate-item "MenuBar*SolveMenu*Execute Commands...") ;; One command (cx-gui-do cx-set-integer-entry "Execute Commands*IntegerEntry1(Defined Commands)" 1) (cx-gui-do cx-activate-item "Execute Commands*IntegerEntry1(Defined Commands)") ;; Save image every frame_every time steps (cx-gui-do cx-set-list-selections "Execute Commands*Frame2*Table2*DropDownList9" '(1)) (cx-gui-do cx-activate-item "Execute Commands*Frame2*Table2*DropDownList9") (cx-gui-do cx-set-text-entry "Execute Commands*Frame2*Table2*TextEntry10" "(disp-save)") (cx-gui-do cx-set-integer-entry "Execute Commands*Frame2*Table2*IntegerEntry8" frame_every) (cx-gui-do cx-set-toggle-button "Execute Commands*Frame2*Table2*CheckButton6" #f) (cx-gui-do cx-activate-item "Execute Commands*Frame2*Table2*CheckButton6") ;; Ok! (cx-gui-do cx-activate-item "Execute Commands*PanelButtons*PushButton1(OK)") ) ;; Create actual movie (define (movie-finish) ;; Create movie from images, remove images afterwards ;; ffmpeg only handles jpg/pnm ok. jpg with 100% quality chosen to save interim space. (display (format #f "Creating movie ~a ... " outputmovie)) (system (format #f "rm -f ~a" outputmovie)) (system (format #f "ffmpeg -i ~a/movie-%04d.jpg -f avi -vcodec mpeg4 -vtag xvid -b 1800 -r ~f ~a" tmpmoviedir (/ (/ 1 (rpgetvar 'physical-time-step)) frame_every) outputmovie)) ;(system (format #f "rm -f ~a/*" tmpmoviedir)) (display "done!") ) ;; Do here once for speed, hope it's not nuked later on. (movie-initialize) (movie-hook) ;; vim:ts=2:sw=2:ft=scheme: