#lang racket/gui
(require (planet williams/simulation/simulation-with-graphics))
(define end-time 720.0)
(define n-pits 7)
(define initial-furnace-temp 1000.0)
(define total-ingots 0)
(define wait-time #f)
(define heat-time #f)
(define leave-temp #f)
(define random-sources (make-random-source-vector 4))
(define furnace-set #f)
(define furnace-temp #f)
(define pit #f)
(define (scheduler)
(for ((i (in-naturals)))
(schedule #:now (ingot i))
(wait (random-exponential (vector-ref random-sources 0) 1.5))))
(define-process (furnace)
(set! furnace-temp (make-continuous-variable initial-furnace-temp))
(work/continuously
(set-variable-dt!
furnace-temp (* (- 2500.0 (variable-value furnace-temp)) 0.05))))
(define-process (ingot i)
(let* ((initial-temp (random-flat (vector-ref random-sources 1) 100.0 200.0))
(heat-coeff (+ (random-gaussian
(vector-ref random-sources 2) 0.05 0.01) 0.07))
(final-temp (random-flat (vector-ref random-sources 3) 800.0 1000.0))
(current-temp (make-continuous-variable initial-temp))
(arrive-time (current-simulation-time))
(start-time #f))
(when (= (modulo i 100) 0)
(accumulate (variable-history current-temp)))
(with-resource (pit)
(set-variable-value! wait-time (- (current-simulation-time) arrive-time))
(queue-insert! furnace-set self)
(set! start-time (current-simulation-time))
(work/continuously
until (>= (variable-value current-temp) final-temp)
(set-variable-dt!
current-temp
(* (- (variable-value furnace-temp) (variable-value current-temp))
heat-coeff)))
(set-variable-value! heat-time (- (current-simulation-time) start-time))
(set-variable-value! leave-temp (variable-value current-temp))
(queue-remove! furnace-set self))
(when (variable-history current-temp)
(write-special
(history-plot (variable-history current-temp)
(format "Ingot ~a Temperature History" i)))
(newline))
(set! total-ingots (+ total-ingots 1))))
(define (stop-sim)
(printf "Report after ~a Simulated Hours - ~a Ingots Processed~n"
(current-simulation-time) total-ingots)
(printf "~n-- Ingot Waiting Time Statistics --~n")
(printf "Mean Wait Time = ~a~n" (variable-mean wait-time))
(printf "Variance = ~a~n" (variable-variance wait-time))
(printf "Maximum Wait Time = ~a~n" (variable-maximum wait-time))
(printf "~n-- Ingot Heating Time Statistics --~n")
(printf "Mean Heat Time = ~a~n" (variable-mean heat-time))
(printf "Variance = ~a~n" (variable-variance heat-time))
(printf "Maximum Heat Time = ~a~n" (variable-maximum heat-time))
(printf "Minimum Heat Time = ~a~n" (variable-minimum heat-time))
(printf "~n-- Final Temperature Statistics --~n")
(printf "Mean Leave Temp = ~a~n" (variable-mean leave-temp))
(printf "Variance = ~a~n" (variable-variance leave-temp))
(printf "Maximum Leave Temp = ~a~n" (variable-maximum leave-temp))
(printf "Minimum Leave Temp = ~a~n" (variable-minimum leave-temp))
(write-special (history-plot (variable-history leave-temp)
"Final Temperature Histogram"))
(newline)
(printf "~n-- Furnace Utilization Statistics --~n")
(printf "Mean No. of Ingots = ~a~n"
(variable-mean (queue-variable-n furnace-set)))
(printf "Variance = ~a~n"
(variable-variance (queue-variable-n furnace-set)))
(printf "Maximum No. of Ingots = ~a~n"
(variable-maximum (queue-variable-n furnace-set)))
(printf "Minimum No. of Ingots = ~a~n"
(variable-minimum (queue-variable-n furnace-set)))
(write-special (history-plot (variable-history (queue-variable-n furnace-set))
"Furnace Utilization History"))
(newline)
(stop-simulation))
(define (initialize)
(current-simulation-max-step-size (/ 1.0 60.0))
(set! total-ingots 0)
(set! wait-time (make-variable))
(set! heat-time (make-variable))
(set! leave-temp (make-variable))
(set! pit (make-resource n-pits))
(set! furnace-set (make-queue))
(accumulate (variable-history (queue-variable-n furnace-set)))
(tally (variable-statistics wait-time))
(tally (variable-statistics heat-time))
(tally (variable-statistics leave-temp))
(tally (variable-history leave-temp))
(schedule #:now (furnace))
(schedule #:at 0.0 (scheduler))
(schedule #:at end-time (stop-sim)))
(define (run-simulation)
(parameterize
((current-output-port (open-output-text-editor text)))
(begin-busy-cursor)
(send run-button enable #f)
(send gauge set-range
(inexact->exact (round end-time)))
(send gauge set-value 0)
(let ((t (make-variable 0.0))) (with-new-simulation-environment
(current-simulation-monitor
(lambda ()
(set-variable-value! t (current-simulation-time))))
(monitor after (set-variable-value! t v)
(send gauge set-value
(inexact->exact (round v))))
(initialize)
(start-simulation)
(send run-button enable #t)
(end-busy-cursor)))))
(define frame
(instantiate frame%
("Furnace Model")))
(define menu-bar
(instantiate menu-bar%
(frame)))
(define file-menu
(instantiate menu%
("&File" menu-bar)))
(define exit-menu-item
(instantiate menu-item%
("E&xit" file-menu)
(callback (lambda (mi e)
(exit)))))
(define edit-menu
(instantiate menu%
("&Edit" menu-bar)))
(define panel-1
(instantiate horizontal-panel%
(frame)
(alignment '(right center))))
(define run-button
(instantiate button%
("&Run" panel-1)
(horiz-margin 4)
(callback (lambda (b e)
(run-simulation)))))
(define canvas
(instantiate editor-canvas%
(frame)
(min-width 500)
(min-height 500)))
(define text
(instantiate text%
()))
(send canvas set-editor text)
(define gauge
(instantiate gauge%
("Progress" 1 frame)))
(send frame show #t)