FLUENT6: transient simulation: stop iterating (and advance to next time step) based on custom convergence monitor


Residuals as the sole automatically evaluated convergence criteria don't always satisfy our needs:
In an unsteady simulation, we want to stop iterating for the current time step and advance to the next time step when the relative change of one or more specified monitor-able quantities (surface average etc.) over the past n iterations is less then a given criterion.

The most recent resolution to this desire is provided as a scheme-based tool in the following file:
<a target=_blank href="ftp://ftp.fluent.de/outgoing/jos/stptmstp5bin.zip">ftp://ftp.fluent.de/outgoing/jos/stptmstp5bin.zip</a>ftp://ftp.fluent.de/outgoing/jos/stptmstp5bin.zip
Please download, unzip, and read "stptmstp.txt". It will explain how to achieve what you probably want.
In the case of questions or problems, please contact your technical customer support representative or Jochen.Schuetze@ansys.com (mailto:Jochen.Schuetze@ansys.com).
______________________________________

Older material, less functional than the above suggestion:

The solution provided is a scheme source code.
It needs to be edited according to the comments provided.

The body of the function "stptmstp-getnewvalue" must be defined by the user. For that, some function call should be used that returns the monitor value to be used. It is usually not trivial to figure out which scheme function to call in order to get and use a surface average (or integral) in scheme program code. More information on this can be found in Solution 515.

Another, usually much preferable (!!!), way is to use the "pick" function (provided in a separate scheme file "ti-to-scm-jos.scm" -- see the second Resolution entry of this Solution) on an arbitrary text (TUI) command. This will "tokenize" the output of the text command and allow you to use whichever bit of it you want.

An example for the definition of stptmstp-getnewvalue is given in the text of the first Resolution entry of this Solution.

A second "Resolution" entry has been added to this Solution -- it gives the contents of a second scheme file (ti-to-scm-jos.scm) which will be needed in conjunction with the scheme file listed in the first resolution.

A third "Resolution" entry has been added to this Solution -- it gives a completely independent approach to the same task.
;;; stptmstp.scm:
;;; Transient simulation:
;;; Stop iterating when a certain monitor quantity
;;; (to be determined with "stptmstp-getnewvalue")
;;; hasn't changed by more than a certain fraction
;;; [of the smaller of the values being compared!]
;;; during the last n time steps.


;;; To use this...
;;; 1. Below, in the definition of the function
;;; "stptmstp-getnewvalue", fill in the gap...
;;; 2. Below, set your preferred values for
;;; a) stptmstp-n
;;; b) stptmstp-maxrelchng
;;; The meanings are explained above.
;;; 3. Load this scheme file in your FLUENT session.
;;; 4. Switch OFF all residual monitor convergence checking.
;;; 5. Under "Solve -- Execute Commands", define TWO items:
;;; a) Every Iterations: (stptmstp-chckcnvrg)
;;; b) Every Time Step: (stptmstp-resetvalues)
;;; 6. Run your transient simulation!
;;;
;;; 7. By the way -- this should even work in steady-state.
;;; Just skip step 5. b) (stptmstp-resetvalues)..!
;;;

(load 'ti-to-scm-jos)

(define stptmstp-getnewvalue
(lambda ()
;;; Insert a scheme function call here that
;;; returns the monitor value to be used:

(string->number (pick "/report/surface-mass-avg pressure-outlet-5 () velocity-magnitude"))

;;; End of insertion.
)) ;;; close parens.
;;;
;;; End of function "stptmstp-getnewvalue"
;;;

(define stptmstp-n 5)

(define stptmstp-maxrelchng 0.0001)

;;;;;;;;
;;;;;;;; Nothing for the user to edit below this line.
;;;;;;;;

(define stptmstp-values '())

(define stptmstp-resetvalues
(lambda ()
(set! stptmstp-values '())))

;;;;;;;;;;;;;;;;;;;;;;;
;; (define mycounter 0)
;; (define stptmstp-getnewvalue
;; (lambda ()
;; (set! mycounter (+ 1 mycounter))
;; mycounter))
;;;;;;;;;;;;;;;;;;;;;;;


(define stptmstp-chckcnvrg
(lambda ()
(if (< (length stptmstp-values) stptmstp-n)
(begin
(set! stptmstp-values (cons (stptmstp-getnewvalue) stptmstp-values))
;;(format "nstptmstp-values: ~an" stptmstp-values)
)
(begin
(set! stptmstp-values (cons (stptmstp-getnewvalue)
(reverse (cdr (reverse stptmstp-values)))))
;;(format "nstptmstp-values: ~an" stptmstp-values)
(if
(<
(let loop ((allvalues (reverse stptmstp-values))
(maxrltvchnge 0))

;;(format "in the loop: allvalues: ~s; maxrltvchnge: ~s.~%"
;; allvalues maxrltvchnge)

(if (pair? (cdr allvalues)) ;; two elements?
(loop
(cdr allvalues)
(max maxrltvchnge
(let* ((old (car allvalues))
(new (car (reverse allvalues)))
(maxnewold (max new old))
(minnewold (min new old))
(difnewold (- maxnewold minnewold))
(rltvchnge (/ difnewold minnewold)))

;;(format "calculating rltvchnge: new: ~a, old: ~a, max: ~a, min: ~a, dif: ~a, rlt: ~a.~%"
;; new old maxnewold minnewold difnewold rltvchnge)

(if (< 0 (* new old)) ;;; same sign?
rltvchnge
1000.))))
maxrltvchnge))
stptmstp-maxrelchng)
(begin
(stptmstp-resetvalues)
(monitor-solution-done "Iterations stopped by stptmstp")))))))

;;(format "nstptmstp: old: ~a --- new: ~a --- rltvchnge: ~an"
;; old new rltvchnge)

;;
;;
;; (let loop ((maxval 0)
;; (i 0))
;; (format "i: ~a; maxval: ~a~%" i maxval)
;; (if (< i 7)
;; (loop (max maxval i) (+ i 1))
;; (max maxval i)))
;;
;;
;; (let loop ((maxval 0)
;; (i 7))
;; (format "i: ~a; maxval: ~a~%" i maxval)
;; (if (> i 0)
;; (loop (max maxval i) (- i 1))
;; (max maxval i)))
;;
;;;; ti-to-scm-jos.scm:
;;
;; Copyright 1991-2004 Fluent Inc.
;; All Rights Reserved.
;;
;;
;; uhb 2004-08-03 : - inherited it from jos, who...
;; inherited it from am, who...
;; inherited it from... ????
;; - subsequently modified
;; jos 2005-03-17 : - reversed interpretation of indices passed
;; to (pick "...." indices) -- count from end.
;; (display-pick-list) modified accordingly.
;; - Adding the following documentation:
;;
;;
;; The command...
;;
;; (pick "/report/projected-surface-area 1 () 0.1 0 1 0")
;;
;; ...OR (identical!)...
;;
;; (pick "/report/projected-surface-area (1) 0.1 0 1 0")
;;
;; ...returns a single string that can be converted to a number using
;; (string->number ...) The string is the last "token" of the output
;; of the TUI command.
;;
;;
;;
;; The command...
;;
;; (pick "/report/projected-surface-area 1 () 0.1 0 1 0" 8)
;;
;; does the same, but the returned string is the last-but-8 element of
;; the list.
;;
;;
;; The command...
;;
;; (pick "/report/projected-surface-area 1 () 0.1 0 1 0" 6 8 10)
;;
;; returns a *list* of three strings containing the last-but-9th,
;; last-but-7th, and last-but-5th element. (Note that the *last*
;; element is addressed by the index '1'..!)
;;
;;
;; OLD COMMENT by uhb as of 2004-08-03
;;
;; ti-command = "text interface command"
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define pick) ; picks item(s) from the output of a ti-command
(define display-pick-list) ; displays the items of the output of a ti-command

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define tokenize
;; splits a string into tokens, which are defined
;; as being separated by delimiters.
(lambda (str)
(let ((l (string->list str))
(result '())
(delimiters (list #space #newline #) #())
(started? #f)
(temp '()))
(for-each
(lambda (c)
(if started?
(if (not (memv c delimiters))
(set! temp (append temp (list c)))
(begin
(set! result (append result (list (list->string temp))))
(set! temp '())
(set! started? #f)))
(if (not (memv c delimiters))
(begin
(set! temp (append temp (list c)))
(set! started? #t)))))
l)
(if started?
(set! result (append result (list (list->string temp)))))
result)))


(let ((pick-list ()))

(set! pick
(lambda (ti-command . pos)
;; picks a token out of the output from ti-command, where
;; ti-command has to be a string. If the optional
;; argument(s) pos is(are) missing, the last token is
;; returned, otherwise the one(s) at position(s) pos.
(let ((value))
(set! pick-list
(reverse
(tokenize (with-output-to-string
(lambda () (ti-menu-load-string ti-command))))))
(set! value
(if (pair? pos)
(map (lambda (i) (list-ref pick-list (- i 1))) pos)
(car pick-list)))
(if (pair? value)
(if (equal? (length value) 1)
(car value); return the single element, not a list
value) ; more that one element, return a list
value) ; not a pair, return it as is
)))

(set! display-pick-list
(lambda arg
;; Without arg, displays the last pick-list in a numbered
;; fashion. An optional argument may be the ti-command from
;; which to generate the pick-list.
(display "n")
(if (pair? arg)
(begin
(display "command output:n")
(set! pick-list
(reverse
(tokenize (with-output-to-string
(lambda () (ti-menu-load-string (car arg)))))))
(display "n")
))
(display "items to pick:n")
(let ((i (length pick-list)))
(for-each
(lambda (t) (format "~5a ... ~an" i t) (set! i (- i 1)))
(reverse pick-list)))
(display "n")))
)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; (pick "/report/projected-surface-area (1) 2e-6 0 0 1")
;; (display-pick-list)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; mrun-qave-f61.scm:
;;; This Scheme function allows the user to monitor the
;;; convergence of the solution based *only* on the
;;; relative change in the average of a field variable
;;; on a list of surfaces
;;;
;;; This Scheme function has been written for use with
;;; FLUENT 6.1.18 or later and only for SINGLE PHASE problems.
;;;
;;; To use:
;;;
;;; 1) load the Scheme file through GUI using
;;;
;;; File>Read>Scheme .. this file (mrun-qave-f61.scm)
;;;
;;; or load the Scheme file through TUI command
;;;
;;; (load "mrun-qave-f61.scm")
;;;
;;; 2) Disable Check Convergence in Solve>Monitor>Residuals for all
;;; equations
;;;
;;; 3) type the following TUI command (example)
;;;
;;;
;;; (gp-run 1000 10 1e-5 "average" 'pressure (list 'outlet))
;;;
;;; The general form of the command is:
;;;
;;; (gp-run niter nchek eps-rep type quantity p-zone-names)
;;;
;;; gp-run is the name of the function and the rest
;;; of 5 names are parameters that the user can specify
;;; for its particular problem; please use the commands
;;; with all their specified characters as they are
;;; written here (paranthesis, apostrophes, double quotes, etc.).
;;;
;;; Notes about the Syntax and the Semantics of the parameters:
;;;
;;; niter = number of iterations to be run
;;;
;;; nchek = number of iterations for which the relative change in the
;;; mass average of the quantity on the monitored
;;; surfaces has to be less than the specified tolerance eps-rep
;;;
;;; eps-rep = convergence criteria for quantity relative change
;;;
;;; type = type of average as a string input;
;;; "average" stands for Area-weighted average;
;;; "mass-average" (or any other string if mistaken)
;;; stands for Mass-weighted average;
;;;
;;; quantity = variable of interest
;;; examples of correct inputs for quantity:
;;; 'pressure
;;; 'temperature
;;; 'velocity-magnitude
;;; (ask support for more correct inputs)
;;;
;;; p-zone-names = list of surface names
;;; examples of correct inputs in the required list format:
;;; (list 'outlet)
;;; (list 'inlet-1 'inlet-2)
;;;
;;; Note - when you specify a list of more than one surface,
;;; one average of the quantity is computed
;;; using the values from all surfaces
;;;
;;;
;;; Therefore, the above example will run maximum 1000 iterations and
;;; once the relative change in static pressure on the surface
;;; named outlet will remain below 1e-5 for 10 consecutive iterations
;;; it will stop. There will be appropriate messages printed
;;; in the console window during the run.
;;;
;;;
;;; Do not edit below this line without calling for support
;;; ========================================================
(define first? #t)
(define list->strip
(lambda (inputlist)
(let ((stri "")
(ll (length inputlist)))
(let loop ((i 0))
(if (< i ll)
(begin
(set! stri (string-append stri " " (number->string (list-ref inputlist i))))
(loop (+ i 1))))
stri ))))

(define (g-surface-average type quantity list-of-surf-names)
(let ((g-surface))
;;;
(set! g-surface
(lambda (typx surfx cell-onlyx?)
(if (equal? typx "average")
(surface-average surfx cell-onlyx?)
(surface-mass-average surfx cell-onlyx?))))
;;;;
(let* ((surf-list (map surface-name->id list-of-surf-names))
(input-strip (list->strip surf-list)))
(if first?
(begin
(ti-menu-load-string (string-append "(cxisetvar 'xy/surfaces "") ()"))
(ti-menu-load-string (string-append "(cxisetvar 'xy/surfaces "") " input-strip ","))
(set! first? #f)))
(let ((of quantity))
(if of
(let ((cell-only? (cx-cell-only-field? 'mixture of))
(surfaces (cxgetvar 'xy/surfaces)))
(client-set-node-values #f)
(client-fill-node-values of)
(cx-fill-face-zone-values surfaces of)
(g-surface type surfaces cell-only?)))))))
;;;

(define (gp-run niter nchek eps-rep qtype quantity p-zone-names)
(let ((continue #t)
(ok? #t)
(rep-old 1)
(rep-new 1)
(rep-change 1)
)
(let loop1 ((i 0))
(if (and (< i niter) continue ok?)
(begin
(if (< eps-rep rep-change)
(begin
(set! ok? (err-protect (ti-menu-load-string "/so/it 1")))
(set! rep-old rep-new)
(set! rep-new (g-surface-average qtype quantity p-zone-names))
(set! rep-change (/ (abs (- rep-new rep-old)) (abs rep-old)))
(format "n ~a more iterations" (- niter (+ i 1)))
(format "n ~ad ~a (SI units)= ~a " qtype quantity rep-new)
(if (> i 0)
(format "t Percentage Change is ~a % n" (* 100 rep-change)))
(loop1 (+ i 1)))
(begin
(do ((ik 1 (+ ik 1)))
(
(or (> ik nchek) (< eps-rep rep-change)(not ok?))
(begin
(if (> ik nchek)(set! continue #f)(set! continue #t))
)
)
(begin
(format "n Make-sure-iteration ~a (~a iterations left in main loop) n" ik (- niter i))
(set! ok? (err-protect (ti-menu-load-string "/so/it 1")))
(set! rep-old rep-new)
(set! rep-new (g-surface-average qtype quantity p-zone-names))
(set! rep-change (/ (abs (- rep-new rep-old)) (abs rep-old)))
(format "n ~ad ~a (SI units)= ~a " qtype quantity rep-new)
(format "t Percentage Change is ~a % n" (* 100 rep-change))
;;;;(set! i (+ i 1))
)
)
(loop1 i))
)
)
(if continue
(begin
(if ok?
(begin
(format "n Main loop of ~a iterations has been completed" niter)
(display continue)))
)
(begin
(if ok?
(begin
(format "n ~a make-sure-iterations kept convergence" nchek)
(display continue)))
)
)))))





Show Form
No comments yet. Be the first to add a comment!