Using fz for parametric studies

library(fz)

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Introduction

The fz package provides R bindings to the funz-fz Python package. It lets you:

fz works with any simulation code that reads text input files and writes text output files. You describe the model in a small dict (or install it as a named alias with fz install).

Installation

# Install the funz-fz Python package into the active reticulate environment
fz_install()

# Verify
fz_available()

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Concepts

Template files

A template is an ordinary input file for your simulator with variable placeholders, e.g.:

# Perfect Gas parameters
pressure = ${P~1.013}    # variable P, default 1.013
volume   = ${V~22.4}     # variable V, default 22.4
moles    = ${n~1.0}

The placeholder syntax ($, {}) is defined by the model dict.

Model dict

The model dict tells fz how to:

  1. find variable placeholders (varprefix, delim),
  2. extract output values from the result files (output).
model <- list(
  varprefix    = "$",
  delim        = "{}",
  formulaprefix = "@",
  commentline  = "#",
  output = list(
    pressure = "grep 'pressure =' output.txt | cut -d= -f2"
  )
)

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

You can also use an installed model alias (a string) instead of an inline dict:

fzl()$models  # lists installed aliases, e.g. "PerfectGas"

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Basic workflow

The typical fz workflow has four steps.

Step 1 — Inspect the template

fzi parses the template and returns the variable names together with their default values:

vars <- fzi("input.txt", model)
# $P [1] 1.013
# $V [1] 22.4
# $n [1] 1.0

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Step 2 — Compile (substitute values)

fzc writes one copy of the input file per parameter combination into output_dir. Each copy goes into a subdirectory named var1=val1,var2=val2,...:

# Single case
fzc("input.txt", list(P = 2.0, V = 11.2), model, output_dir = "compiled")
# writes: compiled/P=2,V=11.2/input.txt  (placeholder replaced with 2.0 / 11.2)

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Supply vectors to generate a full-factorial grid:

# 2 x 3 = 6 cases
fzc("input.txt",
    list(P = c(1.0, 2.0), V = c(10.0, 20.0, 30.0)),
    model,
    output_dir = "compiled")

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Step 3 — Run the model and collect outputs

fzr wraps steps 1–3 and output collection into a single call. It compiles the template, runs the calculator for every case, and returns a data frame:

results <- fzr(
  "input.txt",
  list(P = c(1.0, 2.0, 3.0), V = 22.4),   # 3 cases (V fixed)
  model,
  results_dir = "results",
  calculators = "sh://bash run.sh"           # run.sh executes the simulator
)

# results is a data frame:
#     P    V  pressure
# 1  1.0  22.4   ...
# 2  2.0  22.4   ...
# 3  3.0  22.4   ...

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

The calculators argument accepts:

Step 4 — Read outputs from existing directories

If you already ran the simulator externally, fzo reads the output files:

values <- fzo("results/P=2,V=22.4", model)
# $pressure [1] "2.026"

# Glob to read all cases at once:
all_values <- fzo("results/*", model)

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Algorithm-driven design of experiments

fzd runs an adaptive experiment: the algorithm decides which parameter combinations to evaluate based on previous results. Input variable ranges use "[min;max]" strings:

result <- fzd(
  "input.txt",
  list(P = "[1;5]", V = "[10;30]"),
  model,
  output_expression = "pressure",
  algorithm         = "algorithms/montecarlo_uniform.py",
  algorithm_options = "batch_sample_size=10;max_iterations=5;seed=42"
)

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Algorithms are Python files; fz ships several in algorithms/ (Monte Carlo, surrogate-based optimization, …). You can also write your own.

Listing installed models

fzl shows which model aliases and calculators are installed in ~/.fz/:

info <- fzl()
names(info$models)       # e.g. c("PerfectGas", "Moret")
names(info$calculators)  # e.g. c("sh://")

# Filter by pattern
fzl(models = "Perfect*")

# Probe calculators to verify they are reachable
fzl(check = TRUE)

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Best practices

  1. Test with fzi first — verify the correct variable names are found before running anything.
  2. Use fzc for a dry run — inspect compiled files to confirm placeholder substitution is correct.
  3. Start small — run a handful of cases before launching a large sweep.
  4. Save results — persist the data frame for reproducibility.
saveRDS(results, "fz_results.rds")
write.csv(results, "fz_results.csv", row.names = FALSE)

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Troubleshooting

fz Python package not found:

fz_install()         # install funz-fz into the reticulate environment
fz_available()       # should return TRUE afterwards

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

Variables not found in template: Check that varprefix and delim in your model dict match the syntax used in your template file. Run fzi and inspect the returned list.

Calculator errors: Run the simulator manually on one compiled directory to confirm it works before using fzr.

Further reading

Session info

sessionInfo()

/tmp/RtmpKKKDyA/Rbuild1acc4525105f2/fz/vignettes/modelica-examples.R

mirror server hosted at Truenetwork, Russian Federation.