3. Orchestrating 4C Simulations#
Until now, all the simulation models we have used in QUEENS were Python-based. For a lot of us, this is not the case. From fenics to abaqus, we all have our own preferred solvers. One main advantage of QUEENS is its independence of solver type. This means, to use your QUEENS model with your favorite solver, the only thing you have to do is write an interface.
Since QUEENS and the multiphysics solver 4C share some developers, the QUEENS community already provides a ready-to-go interface. So let’s start there.
The 4C model#
In this example, we’ll have a look at a nonlinear solid mechanics problem. The momentum equation is given by
where \(\boldsymbol{u}\) are the displacements, \(\boldsymbol{\sigma}\) the Cauchy stresses, \(\boldsymbol{b}\) the volumetric body forces, and \(\Omega\) the domain of the solid. For the following examples, \(\boldsymbol{b}=\boldsymbol{0}\), and we prescribe Dirichlet boundary conditions
and a Neumann boundary condition:
We assume a static problem, so \(\ddot{\boldsymbol{u}} = 0\), and use a Saint Venant–Kirchhoff material model
where \(\boldsymbol{S}\) is the second Piola-Kirchhoff stress tensor and \(\boldsymbol{E}\) the Green-Lagrange strain tensor with the Lamé parameters
where \(E\) is the Young’s modulus and \(\nu\) the Poisson’s ratio.
The problem is discretized in space using 40 linear finite elements.
Note: This tutorial is based on the 4C tutorial Preconditioners for Iterative Solvers
Note: In the following, we use PyVista for plotting; however, this might not work for some setups. In that case, set
pyvista_availabletoFalsein the next cell, and please refer to the online tutorial in the documentation for figures.
[1]:
# Set this to False if pyvista is causing the kernel to crash
pyvista_available = True
[2]:
# Define some paths
from pathlib import Path
import queens.utils.config_directories as config_directories
try:
from tutorials.utils import find_repo_root
except ModuleNotFoundError:
# Quick fix to allow the import in a local setting
import sys
REPO_ROOT = Path.cwd().parents[1]
sys.path.insert(0, str(REPO_ROOT))
from tutorials.utils import find_repo_root
NOTEBOOK_DIR = Path.cwd()
QUEENS_BASE_DIR = find_repo_root(NOTEBOOK_DIR)
QUEENS_EXPERIMENTS_DIR = config_directories.base_directory()
TUTORIAL_DIR = QUEENS_BASE_DIR / "tutorials" / "3_orchestrating_4c_simulations"
[3]:
# Let's look at the mesh!
import os
if pyvista_available:
os.environ["PYVISTA_OFF_SCREEN"] = "true"
os.environ["VTK_DEFAULT_RENDER_WINDOW_OFFSCREEN"] = "1"
os.environ["PYVISTA_JUPYTER_BACKEND"] = "static"
import pyvista as pv
fe_mesh = pv.read(TUTORIAL_DIR / "beam_coarse.exo")
pl = pv.Plotter(off_screen=True, title="Finite Element mesh", window_size=(1400, 500))
pl.add_mesh(fe_mesh, show_edges=True, opacity=0.8)
pl.add_mesh(pv.Plane(center=[0, 0, -2.50001], direction=[0, 0, 1]), color="blue") # Gamma_w
pl.add_mesh(pv.Plane(center=[0, 0, 2.50001], direction=[0, 0, 1]), color="red") # Gamma_e
pl.add_axes(line_width=5)
pl.camera_position = [
(1.1321899035097993, -6.851600196807601, 2.7649096132703574),
(0.0, 0.0, 0.275),
(-0.97637930372977, -0.08995062285804697, 0.19644933366041056),
]
pl.show()
/__w/queens/queens/.pixi/envs/dev/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
The red plane is \(\Gamma_e\), the blue one is \(\Gamma_w\).
Simulation Analytics#
Now, we want to have a look at the Cauchy stresses \(\boldsymbol{\sigma}\) for various Young’s moduli \(E\) and Poisson’s ratios \(\nu\). For the purpose of demonstration, let’s assume a uniform distribution for each material parameter.
Of course we use QUEENS, so let’s get started!
[4]:
from queens.distributions import Uniform
from queens.parameters import Parameters
# Let's define the distributions
young = Uniform(10, 10000)
poisson_ratio = Uniform(0, 0.5)
# Let's define the parameters
parameters = Parameters(young=young, poisson_ratio=poisson_ratio)
Now that we have the parameters ready, we need a Driver. In QUEENS terms, drivers call the underlying simulation models, provide the simulation input and handle logging and error management. They are the interfaces to arbitrary simulation software and essentially do everything that is needed to start a single simulation.
As mentioned before, for 4C, these are already provided by the QUEENS community.
Note: This tutorial assumes a working local 4C installation. Please create a symbolic link to your 4C build directory and store it under
<queens-root-dir>/config/4C_buildvia this command:ln -s <path-to-4C-build-directory> <queens-root-dir>/config/4C_build
[5]:
from queens_interfaces.fourc.driver import Fourc
fourc_executable = QUEENS_BASE_DIR / "config" / "4C_build" / "4C"
input_template = TUTORIAL_DIR / "input_template.4C.yaml"
input_mesh = TUTORIAL_DIR / "beam_coarse.exo"
fourc_driver = Fourc(
parameters=parameters, # parameters to run
input_templates=input_template, # input template
executable=fourc_executable, # 4C executable
files_to_copy=[input_mesh], # copy mesh file to experiment directory
)
4C simulations are controlled via yaml input files. They need to be created for every simulation. Therefore, we provide a jinja2 input template to the driver. Jinja2 is a fast, expressive, and extensible templating engine. It starts from a template, for example
MATERIALS:
- MAT: 1
MAT_Struct_StVenantKirchhoff:
YOUNG: {{ young }}
NUE: {{ poisson_ratio }}
DENS: 1
and inserts the desired values (here: young = 1000 and poisson_ratio = 0.3) into the respective placeholders (here: {{ young }} and {{ poisson_ratio }}). This results in:
MATERIALS:
- MAT: 1
MAT_Struct_StVenantKirchhoff:
YOUNG: 1000
NUE: 0.3
DENS: 1
For 4C, this allows us to create inputs for simulation runs without the need for a 4C API! Let’s run this example!
[6]:
import numpy as np
driver_output = fourc_driver.run(
inputs={"young": 1000, "poisson_ratio": 0.3},
job_id="fourc_young_1000_poisson_ratio_03",
num_procs=1,
experiment_dir=Path.cwd(),
experiment_name="fourc_run",
)
Some information:
inputs: is a dict with the parameter names as keys and the values for which we want to evaluate the model.job_id: is the identifier for the 4C run and also creates a folder with the same name where the data is stored.num_procs: 4C is called using MPI. This is the number of processes that 4C will be called with.experiment_dir: is the directory where we find all necessary data for 4C (input template or any other required files).experiment_name: is an identifier of a QUEENS run. This will come in handy when we evaluate 4C multiple times.
Let’s look at the output folder structure of the QUEENS run:
fourc_young_1000_poisson_ratio_03/
├── input_file.4C.yaml
├── input.pickle
├── jobscript.sh
├── metadata.yaml
├── output.pickle
└── output
├── output.control
├── output.log
├── output.mesh.structure.s0
├── output-structure.pvd
└── output-vtk-files
├── structure-00000-0.vtu
├── structure-00000.pvtu
├── structure-00001-0.vtu
└── structure-00001.pvtu
What are those files?
input_file.4C.yaml: is the 4C input file with \(E=1000\) and \(\nu=0.3\)input.pickle: are the input parameters (\(E\) and \(\nu\)) that QUEENS injects into the 4C input templatejobscript.sh: contains the command with which 4C was calledmetadata.yaml: contains metadata of the 4C run (timestamps, timings, job status, …)output.pickle: is the output that QUEENS extracts from the 4C output filesoutput-folder: all the files in here are output files of 4C! The sole exception isoutput.log, to which QUEENS redirected the logging data
Go have a look at the yaml, sh and log files.
Now, let us look at the Cauchy stresses \(\boldsymbol{\sigma}\).
[7]:
# This is just needed for some nice plots
from plot_results import plot_results
if pyvista_available:
plotter = pv.Plotter()
plot_results(
"fourc_young_1000_poisson_ratio_03/output/output-vtk-files/structure-00001.pvtu",
plotter,
)
plotter.show()
We plotted the deformed mesh. The original mesh is displayed as the blue ‘wireframe’. Let us look into the driver output in Python.
[8]:
print("Driver output:", driver_output)
Driver output: {}
As we can see, it’s {}. But why is it {}?
Well, we told the driver how to run a 4C simulation, but never told it which information we want to extract. For this we need a data processor, i.e., an object that is able to extract data from the simulation results.
[9]:
from queens.data_processors import PvdFile
# Create custom data processor from the available PVD file reader
class CustomDataProcessor(PvdFile):
def __init__(
self,
field_name,
failure_value,
file_name_identifier=None,
files_to_be_deleted_regex_lst=None,
):
super().__init__(
field_name,
file_name_identifier,
files_to_be_deleted_regex_lst=files_to_be_deleted_regex_lst,
point_data=False, # We use cell data
)
self.failure_value = failure_value
def get_data_from_file(self, base_dir_file):
# Get the data
data = super().get_data_from_file(base_dir_file)
# Got some data
if data is not None:
data = data.flatten()
# Simulation started but only the first step was exported
if np.abs(data).sum() < 1e-8:
return self.failure_value
# Return result
return data
# Simulation could not even start
else:
return self.failure_value
custom_data_processor = CustomDataProcessor(
field_name="element_cauchy_stresses_xyz", # Name of the field in the pvtu file
file_name_identifier="output-structure.pvd", # Name of the file in the output folder
failure_value=np.nan * np.ones(40 * 6), # NaN for all elements
)
We have defined our data processor, so let’s continue.
[10]:
# Create a new driver
fourc_driver = Fourc(
parameters=parameters,
input_templates=input_template,
executable=fourc_executable,
data_processor=custom_data_processor, # tell the driver to extract the data
files_to_copy=[input_mesh], # copy mesh file to experiment directory
)
# Run the driver again
driver_output = fourc_driver.run(
inputs={"young": 1000, "poisson_ratio": 0.3},
job_id="fourc_young_1000_poisson_ratio_03_with_data_processor",
num_procs=1,
experiment_dir=Path.cwd(),
experiment_name="fourc_run",
)
print("Driver output", driver_output)
print("Key(s) in driver output:", list(driver_output.keys()))
print(
"Number of entries in the \'result\' key:",
len(driver_output["result"]),
"i.e., 40 elements x 6 Cauchy stress values",
)
Driver output {'result': array([ 2.33105756e+01, 2.33105756e+01, 1.36871583e+02, 1.76081898e-01,
-8.12065251e+00, -8.12065251e+00, -8.70380431e-01, -8.70380431e-01,
1.42473762e+02, 7.09472978e-02, 1.60444657e+00, 1.60444657e+00,
-3.19473608e-01, -3.19473608e-01, 1.42331028e+02, 1.17058224e-01,
2.25417129e-01, 2.25417129e-01, -1.84238993e-02, -1.84238993e-02,
1.42260550e+02, -1.06082947e-02, -3.10846146e-03, -3.10846146e-03,
3.76574842e-03, 3.76574842e-03, 1.42255374e+02, -2.80804488e-04,
-2.89206800e-03, -2.89206800e-03, 3.76574842e-03, 3.76574842e-03,
1.42255374e+02, -2.80804488e-04, 2.89206800e-03, 2.89206800e-03,
-1.84238993e-02, -1.84238993e-02, 1.42260550e+02, -1.06082947e-02,
3.10846146e-03, 3.10846146e-03, -3.19473608e-01, -3.19473608e-01,
1.42331028e+02, 1.17058224e-01, -2.25417129e-01, -2.25417129e-01,
-8.70380431e-01, -8.70380431e-01, 1.42473762e+02, 7.09472978e-02,
-1.60444657e+00, -1.60444657e+00, 2.33105756e+01, 2.33105756e+01,
1.36871583e+02, 1.76081898e-01, 8.12065251e+00, 8.12065251e+00,
2.33105756e+01, 2.33105756e+01, 1.36871583e+02, -1.76081898e-01,
8.12065251e+00, -8.12065251e+00, -8.70380431e-01, -8.70380431e-01,
1.42473762e+02, -7.09472978e-02, -1.60444657e+00, 1.60444657e+00,
-3.19473608e-01, -3.19473608e-01, 1.42331028e+02, -1.17058224e-01,
-2.25417129e-01, 2.25417129e-01, -1.84238993e-02, -1.84238993e-02,
1.42260550e+02, 1.06082947e-02, 3.10846146e-03, -3.10846146e-03,
3.76574842e-03, 3.76574842e-03, 1.42255374e+02, 2.80804488e-04,
2.89206800e-03, -2.89206800e-03, 3.76574842e-03, 3.76574842e-03,
1.42255374e+02, 2.80804488e-04, -2.89206800e-03, 2.89206800e-03,
-1.84238993e-02, -1.84238993e-02, 1.42260550e+02, 1.06082947e-02,
-3.10846146e-03, 3.10846146e-03, -3.19473608e-01, -3.19473608e-01,
1.42331028e+02, -1.17058224e-01, 2.25417129e-01, -2.25417129e-01,
-8.70380431e-01, -8.70380431e-01, 1.42473762e+02, -7.09472978e-02,
1.60444657e+00, -1.60444657e+00, 2.33105756e+01, 2.33105756e+01,
1.36871583e+02, -1.76081898e-01, -8.12065251e+00, 8.12065251e+00,
2.33105756e+01, 2.33105756e+01, 1.36871583e+02, -1.76081898e-01,
-8.12065251e+00, 8.12065251e+00, -8.70380431e-01, -8.70380431e-01,
1.42473762e+02, -7.09472978e-02, 1.60444657e+00, -1.60444657e+00,
-3.19473608e-01, -3.19473608e-01, 1.42331028e+02, -1.17058224e-01,
2.25417129e-01, -2.25417129e-01, -1.84238993e-02, -1.84238993e-02,
1.42260550e+02, 1.06082947e-02, -3.10846146e-03, 3.10846146e-03,
3.76574842e-03, 3.76574842e-03, 1.42255374e+02, 2.80804488e-04,
-2.89206800e-03, 2.89206800e-03, 3.76574842e-03, 3.76574842e-03,
1.42255374e+02, 2.80804488e-04, 2.89206800e-03, -2.89206800e-03,
-1.84238993e-02, -1.84238993e-02, 1.42260550e+02, 1.06082947e-02,
3.10846146e-03, -3.10846146e-03, -3.19473608e-01, -3.19473608e-01,
1.42331028e+02, -1.17058224e-01, -2.25417129e-01, 2.25417129e-01,
-8.70380431e-01, -8.70380431e-01, 1.42473762e+02, -7.09472978e-02,
-1.60444657e+00, 1.60444657e+00, 2.33105756e+01, 2.33105756e+01,
1.36871583e+02, -1.76081898e-01, 8.12065251e+00, -8.12065251e+00,
2.33105756e+01, 2.33105756e+01, 1.36871583e+02, 1.76081898e-01,
8.12065251e+00, 8.12065251e+00, -8.70380431e-01, -8.70380431e-01,
1.42473762e+02, 7.09472978e-02, -1.60444657e+00, -1.60444657e+00,
-3.19473608e-01, -3.19473608e-01, 1.42331028e+02, 1.17058224e-01,
-2.25417129e-01, -2.25417129e-01, -1.84238993e-02, -1.84238993e-02,
1.42260550e+02, -1.06082947e-02, 3.10846146e-03, 3.10846146e-03,
3.76574842e-03, 3.76574842e-03, 1.42255374e+02, -2.80804488e-04,
2.89206800e-03, 2.89206800e-03, 3.76574842e-03, 3.76574842e-03,
1.42255374e+02, -2.80804488e-04, -2.89206800e-03, -2.89206800e-03,
-1.84238993e-02, -1.84238993e-02, 1.42260550e+02, -1.06082947e-02,
-3.10846146e-03, -3.10846146e-03, -3.19473608e-01, -3.19473608e-01,
1.42331028e+02, 1.17058224e-01, 2.25417129e-01, 2.25417129e-01,
-8.70380431e-01, -8.70380431e-01, 1.42473762e+02, 7.09472978e-02,
1.60444657e+00, 1.60444657e+00, 2.33105756e+01, 2.33105756e+01,
1.36871583e+02, 1.76081898e-01, -8.12065251e+00, -8.12065251e+00])}
Key(s) in driver output: ['result']
Number of entries in the 'result' key: 240 i.e., 40 elements x 6 Cauchy stress values
The driver output can contain two keys: ‘result’ and ‘gradient’. The first one is supposed to be the output of the model, and the second one the model gradient.
Note: The gradient value is only available for certain models; this particular 4C model does not provide it.
What we did:
We defined a driver using QUEENS to run a 4C simulation via a Python function call
We provided a custom way of extracting simulation results
Although we selected a single process, setting
num_procs>1allows us to run a simulation in parallel without having to change anything in the interface!
The complexity of working with a sophisticated simulation code (without an API) is hidden from the user!
Instead, it is reduced to fourc_driver.run(<arguments>).
Now in the day-to-day of computational mechanics research, we often want to study convergence of a model depending on certain parameters. In this example, we’ll have a look at parameter combinations of \(E \in [10,10000]\) and \(\nu \in [0,0.5]\) which lead to a failing simulation. Let’s evaluate the 4C model on a grid of \(4 \times 21\) points.
[11]:
# Make it less verbose
import logging
logging.getLogger("distributed").setLevel(logging.WARN)
from queens.schedulers import Local
from queens.iterators import Grid
from queens.models import Simulation
from queens.global_settings import GlobalSettings
from queens.main import run_iterator
from queens.utils.io import load_result
n_grid_points_young = 4
n_grid_points_poisson_ratio = 21
grid_experiment_name = f"grid_{n_grid_points_young}x{n_grid_points_poisson_ratio}"
grid_output = None
if __name__ == "__main__":
Path("grid").mkdir(exist_ok=True)
with GlobalSettings(
experiment_name=grid_experiment_name,
output_dir="grid",
) as gs:
scheduler = Local(
gs.experiment_name,
num_jobs=4, # 4 simulations in parallel
num_procs=1, # each simulation uses 1 process
)
model = Simulation(scheduler, fourc_driver)
iterator = Grid(
model=model,
parameters=parameters,
global_settings=gs,
result_description={"write_results": True},
grid_design={
"young": {
"num_grid_points": n_grid_points_young,
"axis_type": "log10",
"data_type": "FLOAT",
},
"poisson_ratio": {
"num_grid_points": n_grid_points_poisson_ratio,
"axis_type": "lin",
"data_type": "FLOAT",
},
},
)
run_iterator(iterator, gs)
grid_output = load_result(gs.result_file("pickle"))
.**.
I I
* *
:. .:
I I
::: .* *. :*:
I * *. .* * I
.: *:*:::: I I ::::*:* :.
:: :I: ::.* *.:: :I: ::
:. * *: .V. .V. :* * .:
:. I :: I*. *I :: I .*
*. :: .* :: :: :* :: *: :* .*
*. I * I :**: I * I .*
*.:. I* ** *I .:.*
*:I :*.* :: *: *.*: I.*
*I: :* .** *I. *: :**
*V *. .*. *II* .*. .* V*
** ..:*I***I*:::: ::::*I***I*:.. **
...... ......
:*IV$$$V*: VV: *VV VVVVVVVVVVVF *VVVVVVVVVVV. .VF. :VI :FV$$$V*:
*$$*:. .:*V$* $$: *$V $$*......... *$I......... .$$$* *$V V$F. .:FV.
V$* *$$. $$: *$V $$: *$F .$$F$V. *$V .$$.
V$F *$V $$: *$V $$: *$I .$$ .V$* *$V F$$*:.
$$: :$$ $$: *$V $$$VVVVVVVV *$$VVVVVVVV: .$$ *$V. *$V .*FV$$V*.
I$F ** *$V $$: *$V $$: *$F .$$ .I$* *$V .*$$*
V$* :V$F$$. I$F V$* $$: *$F .$$ :$$I$V *$$
*$$*:. .:*$$$F F$V*....*V$* $$*......... *$I......... .$$ F$$V V$*: .:V$*
:*IV$$VI*: :I: .*FVVVVF: VVVVVVVVVVVV *VVVVVVVVVVV. .VV :VI :*VV$$VI*.
QUEENS (Quantification of Uncertain Effects in ENgineering Systems):
a Python framework for solver-independent multi-query
analyses of large-scale computational models.
+---------------------------------------------------------------------------------------------------+
| Local |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| self : <queens.schedulers.local.Local object at 0x770e73aeca10> |
| experiment_name : 'grid_4x21' |
| num_jobs : 4 |
| num_procs : 1 |
| restart_workers : False |
| verbose : True |
| experiment_base_dir : None |
| overwrite_existing_experiment : False |
+---------------------------------------------------------------------------------------------------+
2026-11-10 09:19:03,560 - distributed.http.proxy - INFO - To route to workers diagnostics web server please install jupyter-server-proxy: python -m pip install jupyter-server-proxy
2026-11-10 09:19:03,575 - distributed.scheduler - INFO - State start
2026-11-10 09:19:03,578 - distributed.scheduler - INFO - Scheduler at: tcp://127.0.0.1:41455
2026-11-10 09:19:03,578 - distributed.scheduler - INFO - dashboard at: http://127.0.0.1:8787/status
2026-11-10 09:19:03,579 - distributed.scheduler - INFO - Registering Worker plugin shuffle
2026-11-10 09:19:03,587 - distributed.nanny - INFO - Start Nanny at: 'tcp://127.0.0.1:37199'
2026-11-10 09:19:03,589 - distributed.nanny - INFO - Start Nanny at: 'tcp://127.0.0.1:33871'
2026-11-10 09:19:03,591 - distributed.nanny - INFO - Start Nanny at: 'tcp://127.0.0.1:36505'
2026-11-10 09:19:03,593 - distributed.nanny - INFO - Start Nanny at: 'tcp://127.0.0.1:35687'
2026-11-10 09:19:03,987 - distributed.worker - INFO - Start worker at: tcp://127.0.0.1:40853
2026-11-10 09:19:03,988 - distributed.worker - INFO - Listening to: tcp://127.0.0.1:40853
2026-11-10 09:19:03,988 - distributed.worker - INFO - Worker name: 0
2026-11-10 09:19:03,988 - distributed.worker - INFO - dashboard at: 127.0.0.1:39939
2026-11-10 09:19:03,988 - distributed.worker - INFO - Waiting to connect to: tcp://127.0.0.1:41455
2026-11-10 09:19:03,988 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:03,988 - distributed.worker - INFO - Threads: 1
2026-11-10 09:19:03,988 - distributed.worker - INFO - Memory: 3.90 GiB
2026-11-10 09:19:03,988 - distributed.worker - INFO - Local Directory: /tmp/dask-scratch-space/worker-pcsbo0sy
2026-11-10 09:19:03,988 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:03,996 - distributed.worker - INFO - Start worker at: tcp://127.0.0.1:42383
2026-11-10 09:19:03,997 - distributed.worker - INFO - Listening to: tcp://127.0.0.1:42383
2026-11-10 09:19:03,997 - distributed.worker - INFO - Worker name: 2
2026-11-10 09:19:03,997 - distributed.worker - INFO - dashboard at: 127.0.0.1:37735
2026-11-10 09:19:03,997 - distributed.worker - INFO - Waiting to connect to: tcp://127.0.0.1:41455
2026-11-10 09:19:03,997 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:03,997 - distributed.worker - INFO - Threads: 1
2026-11-10 09:19:03,998 - distributed.scheduler - INFO - Register worker addr: tcp://127.0.0.1:40853 name: 0
2026-11-10 09:19:03,997 - distributed.worker - INFO - Memory: 3.90 GiB
2026-11-10 09:19:03,997 - distributed.worker - INFO - Local Directory: /tmp/dask-scratch-space/worker-w4inuj_2
2026-11-10 09:19:03,997 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:04,001 - distributed.worker - INFO - Start worker at: tcp://127.0.0.1:43697
2026-11-10 09:19:04,001 - distributed.worker - INFO - Listening to: tcp://127.0.0.1:43697
2026-11-10 09:19:04,001 - distributed.worker - INFO - Worker name: 1
2026-11-10 09:19:04,001 - distributed.worker - INFO - dashboard at: 127.0.0.1:34083
2026-11-10 09:19:04,001 - distributed.worker - INFO - Waiting to connect to: tcp://127.0.0.1:41455
2026-11-10 09:19:04,001 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:04,001 - distributed.worker - INFO - Threads: 1
2026-11-10 09:19:04,001 - distributed.worker - INFO - Memory: 3.90 GiB
2026-11-10 09:19:04,001 - distributed.worker - INFO - Local Directory: /tmp/dask-scratch-space/worker-sy90_ren
2026-11-10 09:19:04,001 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:04,003 - distributed.scheduler - INFO - Starting worker compute stream, tcp://127.0.0.1:40853
2026-11-10 09:19:04,003 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:44934
2026-11-10 09:19:04,004 - distributed.worker - INFO - Starting Worker plugin shuffle
2026-11-10 09:19:04,005 - distributed.worker - INFO - Registered to: tcp://127.0.0.1:41455
2026-11-10 09:19:04,005 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:04,007 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:41455
2026-11-10 09:19:04,010 - distributed.scheduler - INFO - Register worker addr: tcp://127.0.0.1:42383 name: 2
2026-11-10 09:19:04,010 - distributed.scheduler - INFO - Starting worker compute stream, tcp://127.0.0.1:42383
2026-11-10 09:19:04,011 - distributed.worker - INFO - Starting Worker plugin shuffle
2026-11-10 09:19:04,011 - distributed.worker - INFO - Registered to: tcp://127.0.0.1:41455
2026-11-10 09:19:04,012 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:44946
2026-11-10 09:19:04,012 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:04,013 - distributed.scheduler - INFO - Register worker addr: tcp://127.0.0.1:43697 name: 1
2026-11-10 09:19:04,013 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:41455
2026-11-10 09:19:04,014 - distributed.worker - INFO - Starting Worker plugin shuffle
2026-11-10 09:19:04,014 - distributed.scheduler - INFO - Starting worker compute stream, tcp://127.0.0.1:43697
2026-11-10 09:19:04,014 - distributed.worker - INFO - Registered to: tcp://127.0.0.1:41455
2026-11-10 09:19:04,014 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:04,015 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:44962
2026-11-10 09:19:04,015 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:41455
2026-11-10 09:19:04,025 - distributed.worker - INFO - Start worker at: tcp://127.0.0.1:43919
2026-11-10 09:19:04,025 - distributed.worker - INFO - Listening to: tcp://127.0.0.1:43919
2026-11-10 09:19:04,025 - distributed.worker - INFO - Worker name: 3
2026-11-10 09:19:04,025 - distributed.worker - INFO - dashboard at: 127.0.0.1:36031
2026-11-10 09:19:04,025 - distributed.worker - INFO - Waiting to connect to: tcp://127.0.0.1:41455
2026-11-10 09:19:04,025 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:04,025 - distributed.worker - INFO - Threads: 1
2026-11-10 09:19:04,025 - distributed.worker - INFO - Memory: 3.90 GiB
2026-11-10 09:19:04,025 - distributed.worker - INFO - Local Directory: /tmp/dask-scratch-space/worker-gt5uc_wu
2026-11-10 09:19:04,025 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:04,030 - distributed.scheduler - INFO - Register worker addr: tcp://127.0.0.1:43919 name: 3
2026-11-10 09:19:04,030 - distributed.scheduler - INFO - Starting worker compute stream, tcp://127.0.0.1:43919
2026-11-10 09:19:04,031 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:44974
2026-11-10 09:19:04,031 - distributed.worker - INFO - Starting Worker plugin shuffle
2026-11-10 09:19:04,031 - distributed.worker - INFO - Registered to: tcp://127.0.0.1:41455
2026-11-10 09:19:04,031 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:04,031 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:41455
2026-11-10 09:19:04,068 - distributed.scheduler - INFO - Receive client connection: Client-c5e1e7a9-dce7-11f1-8905-4676ccbaa09b
2026-11-10 09:19:04,069 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:44982
To view the Dask dashboard open this link in your browser: http://127.0.0.1:8787/status
+---------------------------------------------------------------------------------------------------+
| Simulation |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| self : <queens.models.simulation.Simulation object at 0x770e739228d0> |
| scheduler : <queens.schedulers.local.Local object at 0x770e73aeca10> |
| driver : <queens_interfaces.fourc.driver.Fourc object at 0x770ea4409b80> |
+---------------------------------------------------------------------------------------------------+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Grid |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| self : <queens.iterators.grid.Grid object at 0x770e732ac950> |
| model : <queens.models.simulation.Simulation object at 0x770e739228d0> |
| parameters : <queens.parameters.parameters.Parameters object at 0x770ee5e20560> |
| global_settings : <queens.global_settings.GlobalSettings object at 0x770e8021b290> |
| result_description : {'write_results': True} |
| grid_design : {'young': {'num_grid_points': 4, 'axis_type': 'log10', 'data_type': 'FLOAT'}, 'poisson_ratio': {'num_grid_points': 21, 'axis_type': 'lin', 'data_type': 'FLOAT'}} |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+---------------------------------------------------------------------------------------------------+
| git information |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| commit hash : cf8e531d09a5049bec8a3ad5858c6c338df0f9f9 |
| branch : main |
| clean working tree : False |
+---------------------------------------------------------------------------------------------------+
Grid for experiment: grid_4x21
Starting Analysis...
99%|█████████▉| 83/84 [00:19<00:00, 2.92it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 0 - 83 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 84 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 1.996e+01s |
| average time per parallel job : 9.503e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 84/84 [00:19<00:00, 4.21it/s]
Time for CALCULATION: 19.971182107925415 s
2026-11-10 09:19:24,192 - distributed.scheduler - INFO - Retire worker addresses (stimulus_id='retire-workers-1794302364.1926038') (0, 1, 2, 3)
2026-11-10 09:19:24,193 - distributed.nanny - INFO - Closing Nanny at 'tcp://127.0.0.1:37199'. Reason: nanny-close
2026-11-10 09:19:24,193 - distributed.nanny - INFO - Nanny asking worker to close. Reason: nanny-close
2026-11-10 09:19:24,194 - distributed.nanny - INFO - Closing Nanny at 'tcp://127.0.0.1:33871'. Reason: nanny-close
2026-11-10 09:19:24,194 - distributed.worker - INFO - Stopping worker at tcp://127.0.0.1:40853. Reason: nanny-close
2026-11-10 09:19:24,195 - distributed.nanny - INFO - Nanny asking worker to close. Reason: nanny-close
2026-11-10 09:19:24,194 - distributed.worker - INFO - Removing Worker plugin shuffle
2026-11-10 09:19:24,195 - distributed.core - INFO - Connection to tcp://127.0.0.1:41455 has been closed.
2026-11-10 09:19:24,195 - distributed.nanny - INFO - Closing Nanny at 'tcp://127.0.0.1:36505'. Reason: nanny-close
2026-11-10 09:19:24,196 - distributed.nanny - INFO - Nanny asking worker to close. Reason: nanny-close
2026-11-10 09:19:24,196 - distributed.worker - INFO - Stopping worker at tcp://127.0.0.1:43697. Reason: nanny-close
2026-11-10 09:19:24,196 - distributed.worker - INFO - Removing Worker plugin shuffle
2026-11-10 09:19:24,197 - distributed.nanny - INFO - Worker closed
2026-11-10 09:19:24,197 - distributed.nanny - INFO - Closing Nanny at 'tcp://127.0.0.1:35687'. Reason: nanny-close
2026-11-10 09:19:24,197 - distributed.core - INFO - Connection to tcp://127.0.0.1:41455 has been closed.
2026-11-10 09:19:24,198 - distributed.nanny - INFO - Nanny asking worker to close. Reason: nanny-close
2026-11-10 09:19:24,199 - distributed.core - INFO - Received 'close-stream' from tcp://127.0.0.1:44934; closing.
2026-11-10 09:19:24,199 - distributed.nanny - INFO - Worker closed
2026-11-10 09:19:24,199 - distributed.core - INFO - Received 'close-stream' from tcp://127.0.0.1:44962; closing.
2026-11-10 09:19:24,200 - distributed.scheduler - INFO - Remove worker addr: tcp://127.0.0.1:40853 name: 0 (stimulus_id='handle-worker-cleanup-1794302364.2003953')
2026-11-10 09:19:24,201 - distributed.scheduler - INFO - Remove worker addr: tcp://127.0.0.1:43697 name: 1 (stimulus_id='handle-worker-cleanup-1794302364.201078')
2026-11-10 09:19:24,200 - distributed.worker - INFO - Stopping worker at tcp://127.0.0.1:42383. Reason: nanny-close
2026-11-10 09:19:24,200 - distributed.worker - INFO - Removing Worker plugin shuffle
2026-11-10 09:19:24,200 - distributed.worker - INFO - Stopping worker at tcp://127.0.0.1:43919. Reason: nanny-close
2026-11-10 09:19:24,200 - distributed.worker - INFO - Removing Worker plugin shuffle
2026-11-10 09:19:24,201 - distributed.core - INFO - Connection to tcp://127.0.0.1:41455 has been closed.
2026-11-10 09:19:24,201 - distributed.core - INFO - Connection to tcp://127.0.0.1:41455 has been closed.
2026-11-10 09:19:24,202 - distributed.core - INFO - Received 'close-stream' from tcp://127.0.0.1:44946; closing.
2026-11-10 09:19:24,203 - distributed.core - INFO - Received 'close-stream' from tcp://127.0.0.1:44974; closing.
2026-11-10 09:19:24,203 - distributed.nanny - INFO - Worker closed
2026-11-10 09:19:24,203 - distributed.scheduler - INFO - Remove worker addr: tcp://127.0.0.1:42383 name: 2 (stimulus_id='handle-worker-cleanup-1794302364.2038977')
2026-11-10 09:19:24,204 - distributed.scheduler - INFO - Remove worker addr: tcp://127.0.0.1:43919 name: 3 (stimulus_id='handle-worker-cleanup-1794302364.2042563')
2026-11-10 09:19:24,204 - distributed.scheduler - INFO - Lost all workers
2026-11-10 09:19:24,205 - distributed.nanny - INFO - Worker closed
2026-11-10 09:19:24,671 - distributed.nanny - INFO - Nanny at 'tcp://127.0.0.1:35687' closed.
2026-11-10 09:19:24,672 - distributed.nanny - INFO - Nanny at 'tcp://127.0.0.1:33871' closed.
2026-11-10 09:19:24,672 - distributed.nanny - INFO - Nanny at 'tcp://127.0.0.1:36505' closed.
2026-11-10 09:19:24,676 - distributed.nanny - INFO - Nanny at 'tcp://127.0.0.1:37199' closed.
2026-11-10 09:19:24,677 - distributed.scheduler - INFO - Closing scheduler. Reason: unknown
2026-11-10 09:19:24,678 - distributed.scheduler - INFO - Scheduler closing all comms
[12]:
# Let's plot the data
grid_points = grid_output["input_data"]
cauchy_stresses = grid_output["raw_output_data"]["result"]
import matplotlib.pyplot as plt
converged_samples = []
failed_samples = []
failed = []
for input_sample, cauchy_output in zip(grid_points, cauchy_stresses, strict=True):
if np.isnan(cauchy_output).any():
failed_samples.append(input_sample)
failed.append(1)
else:
converged_samples.append(input_sample)
failed.append(0)
converged_samples = np.array(converged_samples)
failed_samples = np.array(failed_samples)
failed = np.array(failed)
fig, ax = plt.subplots(figsize=(12, 8))
ax.contourf(
grid_points[:, 0].reshape(21, 4),
grid_points[:, 1].reshape(21, 4),
failed.reshape(21, 4),
levels=[0, 0.000001],
)
for i, gp in enumerate(grid_points):
plt.text(gp[0] * 1.04, gp[1], i)
ax.scatter(converged_samples[:, 0], converged_samples[:, 1], c="b", label="Converged")
ax.scatter(failed_samples[:, 0], failed_samples[:, 1], c="r", label="Failed")
ax.set_xlim(10 * 0.9, 10000 * 1.2)
ax.set_yticks(np.linspace(0, 0.5, 11))
ax.set_ylim(-0.01, 0.515)
ax.set_xlabel("Young's modulus $E$")
ax.set_xscale("log")
ax.set_ylabel("Poisson ratio $\\nu$")
fig.suptitle("Grid study 4C")
ax.legend()
fig.tight_layout()
plt.show()
Each point represents one simulation, i.e., one 4C run with different parameters. The number next to it is the job id, so the unique identifier for this simulation for QUEENS. The color of the points:
blue: The simulation ran through and returned a value.
red: The simulation failed and NaN was returned.
A colored background indicates the region of the parameter space leading to converging results.
Previously, we called 4C using the driver directly. However, when using QUEENS iterators, this won’t work anymore. Instead, we need a Model. The difference is that a driver handles a single simulation, whereas a model accepts a list of relevant input samples / configurations.
When working with drivers, the Simulation model is used. Besides a driver, this requires a Scheduler. As the name suggests, schedulers schedule evaluations of the driver. The scheduler also handles the evaluation of multiple driver calls at the same time. Keep in mind that each driver call can itself be parallelized with MPI, such that QUEENS natively supports nested parallelism!
Since we are doing our computations locally, we use a Local scheduler. However, there is also a Cluster scheduler which is able to submit jobs on high performance clusters using SLURM, PBS etc.
The scheduler also creates the required folder structure for an experiment. The default base directory is given by config_directories.base_directory(). For the grid iterator, it looks like this:
grid_4x21/
├── 0
├── 1
...
├── 80
├── 81
├── 82
├── 83
├── 9
└── input_template.4C.yaml
Each number is a job with its output:
10
├── input_file.4C.yaml
├── input.pickle
├── jobscript.sh
├── metadata.yaml
├── output.pickle
└── output
├── output.control
├── output.log
├── output.mesh.structure.s0
├── output-structure.pvd
└── output-vtk-files
├── structure-00000-0.vtu
├── structure-00000.pvtu
├── structure-00001-0.vtu
└── structure-00001.pvtu
Once more, have a look at the files. In particular look at the log files of the failed simulations.
[13]:
# Let's look at some simulation outputs!
if pyvista_available:
job_ids = [0, 41, 50, 75]
plotter = pv.Plotter(shape=(2, 2))
for i in range(2):
for j in range(2):
plotter.subplot(i, j)
job_id = job_ids[i * 2 + j]
file_path = QUEENS_EXPERIMENTS_DIR / f"{grid_experiment_name}/{job_id}/output/output-vtk-files/structure-00001.pvtu"
plotter.add_text(f"Job: {job_id}")
plot_results(file_path, plotter, f"E={grid_points[job_id][0]}, nu={np.round(grid_points[job_id][1],decimals=4)}: Cauchy stress zz\n",)
plotter.show()
In summary, we employed QUEENS to do some simulation analytics of a 4C model. We identified failed simulations, looked at the outputs, and extracted data.
Calibration#
Now, let’s imagine we have some experimental measurements of the Cauchy stresses at the element centers \(\boldsymbol{\sigma}_\text{ex}\) of a real-life cantilever. We can now use this to calibrate our parameters \(E\) and \(\nu\) from experiment.
Note: We assume that the 4C model is able to predict the real-word accurately, i.e, we have the right boundary conditions, constitutive law etc.
To do so, we’ll use deterministic optimization to minimize the difference between simulated and measured stresses:
where \(\boldsymbol{\sigma}_e(E,\nu)\) are the elementwise stresses obtained from the 4C model evaluated at \(E, \nu\), where the subscript \(e\) is the element id.
Before we start the optimization, we need to change our parameter space. As we previously identified, the simulation model does not converge for \(\nu > 0.45\). So in order to make meaningful predictions, let’s change the parameter space.
[14]:
# Reduced parameter space for the poisson ratio
poisson_ratio = Uniform(0, 0.45)
parameters = Parameters(young=young, poisson_ratio=poisson_ratio)
[15]:
# Let's implement the loss function
from queens.models._model import Model
class LossFunction(Model):
def __init__(self, experimental_cauchy_stresses, forward_model):
self.experimental_cauchy_stresses = experimental_cauchy_stresses
self.forward_model = forward_model
super().__init__()
def _evaluate(self, samples):
element_cauchy_stresses = self.forward_model.evaluate(samples)["result"]
difference = element_cauchy_stresses - np.tile(
self.experimental_cauchy_stresses, (len(samples), 1)
)
squared_norm = (difference**2).sum(axis=1) + (difference[:, 3:] ** 2).sum(
axis=1
) # the output is only a symmetrical tensor, so we have to add the offdiagonal terms once more
squared_norm /= 40 # 40 elements
return {"result": squared_norm.reshape(-1)}
def grad(self, samples, upstream_gradient):
pass
from experimental_data import experimental_elementwise_cauchy_stress
Ok, now let’s set up the optimization using the L-BFGS-B algorithm.
[16]:
from scipy.optimize import Bounds
from queens.iterators import DeterministicOptimization
optimum = None
if __name__ == "__main__":
Path("optimization").mkdir(exist_ok=True)
with GlobalSettings(
experiment_name="optimization_young_poisson_ratio", output_dir="optimization"
) as gs:
scheduler = Local(
gs.experiment_name,
num_jobs=4, # 4 simulations in parallel
num_procs=1, # each simulation uses 1 process
)
custom_data_processor = CustomDataProcessor(
field_name="element_cauchy_stresses_xyz", # Name of the field in the pvtu file
file_name_identifier="output-structure.pvd", # Name of the file in the output folder
failure_value=np.nan * np.ones(40 * 6), # NaN for all elements
files_to_be_deleted_regex_lst=[
"output.control",
"*.mesh.s0",
"output-vtk-files/*",
], # Delete these files after we've extracted the data to save storage space
)
fourc_driver = Fourc(
parameters=parameters,
input_templates=input_template,
executable=fourc_executable,
data_processor=custom_data_processor, # tell the driver to extract the data
files_to_copy=[input_mesh], # copy mesh file to experiment directory
)
model = Simulation(scheduler, fourc_driver)
loss_function = LossFunction(experimental_elementwise_cauchy_stress, model)
optimization = DeterministicOptimization(
loss_function,
parameters,
gs,
initial_guess=[200, 0.4],
result_description={"write_results": True},
objective_and_jacobian=True,
bounds=Bounds([10, 0], [10000, 0.45]),
algorithm="L-BFGS-B",
max_feval=1000,
)
run_iterator(optimization, gs)
optimum = optimization.solution.x
.**.
I I
* *
:. .:
I I
::: .* *. :*:
I * *. .* * I
.: *:*:::: I I ::::*:* :.
:: :I: ::.* *.:: :I: ::
:. * *: .V. .V. :* * .:
:. I :: I*. *I :: I .*
*. :: .* :: :: :* :: *: :* .*
*. I * I :**: I * I .*
*.:. I* ** *I .:.*
*:I :*.* :: *: *.*: I.*
*I: :* .** *I. *: :**
*V *. .*. *II* .*. .* V*
** ..:*I***I*:::: ::::*I***I*:.. **
...... ......
:*IV$$$V*: VV: *VV VVVVVVVVVVVF *VVVVVVVVVVV. .VF. :VI :FV$$$V*:
*$$*:. .:*V$* $$: *$V $$*......... *$I......... .$$$* *$V V$F. .:FV.
V$* *$$. $$: *$V $$: *$F .$$F$V. *$V .$$.
V$F *$V $$: *$V $$: *$I .$$ .V$* *$V F$$*:.
$$: :$$ $$: *$V $$$VVVVVVVV *$$VVVVVVVV: .$$ *$V. *$V .*FV$$V*.
I$F ** *$V $$: *$V $$: *$F .$$ .I$* *$V .*$$*
V$* :V$F$$. I$F V$* $$: *$F .$$ :$$I$V *$$
*$$*:. .:*$$$F F$V*....*V$* $$*......... *$I......... .$$ F$$V V$*: .:V$*
:*IV$$VI*: :I: .*FVVVVF: VVVVVVVVVVVV *VVVVVVVVVVV. .VV :VI :*VV$$VI*.
QUEENS (Quantification of Uncertain Effects in ENgineering Systems):
a Python framework for solver-independent multi-query
analyses of large-scale computational models.
+---------------------------------------------------------------------------------------------------+
| Local |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| self : <queens.schedulers.local.Local object at 0x770e70474680> |
| experiment_name : 'optimization_young_poisson_ratio' |
| num_jobs : 4 |
| num_procs : 1 |
| restart_workers : False |
| verbose : True |
| experiment_base_dir : None |
| overwrite_existing_experiment : False |
+---------------------------------------------------------------------------------------------------+
2026-11-10 09:19:25,437 - distributed.scheduler - INFO - State start
2026-11-10 09:19:25,440 - distributed.scheduler - INFO - Scheduler at: tcp://127.0.0.1:35689
2026-11-10 09:19:25,440 - distributed.scheduler - INFO - dashboard at: http://127.0.0.1:8787/status
2026-11-10 09:19:25,441 - distributed.scheduler - INFO - Registering Worker plugin shuffle
2026-11-10 09:19:25,449 - distributed.nanny - INFO - Start Nanny at: 'tcp://127.0.0.1:44399'
2026-11-10 09:19:25,450 - distributed.nanny - INFO - Start Nanny at: 'tcp://127.0.0.1:41577'
2026-11-10 09:19:25,452 - distributed.nanny - INFO - Start Nanny at: 'tcp://127.0.0.1:41745'
2026-11-10 09:19:25,454 - distributed.nanny - INFO - Start Nanny at: 'tcp://127.0.0.1:38973'
2026-11-10 09:19:25,890 - distributed.worker - INFO - Start worker at: tcp://127.0.0.1:43819
2026-11-10 09:19:25,890 - distributed.worker - INFO - Start worker at: tcp://127.0.0.1:46397
2026-11-10 09:19:25,890 - distributed.worker - INFO - Listening to: tcp://127.0.0.1:46397
2026-11-10 09:19:25,890 - distributed.worker - INFO - Worker name: 3
2026-11-10 09:19:25,890 - distributed.worker - INFO - dashboard at: 127.0.0.1:37365
2026-11-10 09:19:25,890 - distributed.worker - INFO - Listening to: tcp://127.0.0.1:43819
2026-11-10 09:19:25,890 - distributed.worker - INFO - Worker name: 2
2026-11-10 09:19:25,890 - distributed.worker - INFO - dashboard at: 127.0.0.1:34919
2026-11-10 09:19:25,890 - distributed.worker - INFO - Waiting to connect to: tcp://127.0.0.1:35689
2026-11-10 09:19:25,890 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,890 - distributed.worker - INFO - Threads: 1
2026-11-10 09:19:25,890 - distributed.worker - INFO - Waiting to connect to: tcp://127.0.0.1:35689
2026-11-10 09:19:25,890 - distributed.worker - INFO - Memory: 3.90 GiB
2026-11-10 09:19:25,890 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,890 - distributed.worker - INFO - Local Directory: /tmp/dask-scratch-space/worker-u8dkh5wk
2026-11-10 09:19:25,890 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,890 - distributed.worker - INFO - Threads: 1
2026-11-10 09:19:25,891 - distributed.worker - INFO - Memory: 3.90 GiB
2026-11-10 09:19:25,891 - distributed.worker - INFO - Local Directory: /tmp/dask-scratch-space/worker-we2odjcr
2026-11-10 09:19:25,891 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,891 - distributed.worker - INFO - Start worker at: tcp://127.0.0.1:40655
2026-11-10 09:19:25,892 - distributed.worker - INFO - Listening to: tcp://127.0.0.1:40655
2026-11-10 09:19:25,892 - distributed.worker - INFO - Worker name: 1
2026-11-10 09:19:25,892 - distributed.worker - INFO - dashboard at: 127.0.0.1:46559
2026-11-10 09:19:25,892 - distributed.worker - INFO - Waiting to connect to: tcp://127.0.0.1:35689
2026-11-10 09:19:25,892 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,892 - distributed.worker - INFO - Threads: 1
2026-11-10 09:19:25,892 - distributed.worker - INFO - Memory: 3.90 GiB
2026-11-10 09:19:25,892 - distributed.worker - INFO - Local Directory: /tmp/dask-scratch-space/worker-4nzdpf8r
2026-11-10 09:19:25,892 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,890 - distributed.worker - INFO - Start worker at: tcp://127.0.0.1:38667
2026-11-10 09:19:25,892 - distributed.worker - INFO - Listening to: tcp://127.0.0.1:38667
2026-11-10 09:19:25,892 - distributed.worker - INFO - Worker name: 0
2026-11-10 09:19:25,892 - distributed.worker - INFO - dashboard at: 127.0.0.1:44975
2026-11-10 09:19:25,892 - distributed.worker - INFO - Waiting to connect to: tcp://127.0.0.1:35689
2026-11-10 09:19:25,892 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,892 - distributed.worker - INFO - Threads: 1
2026-11-10 09:19:25,892 - distributed.worker - INFO - Memory: 3.90 GiB
2026-11-10 09:19:25,892 - distributed.worker - INFO - Local Directory: /tmp/dask-scratch-space/worker-ah5tlneh
2026-11-10 09:19:25,892 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,898 - distributed.scheduler - INFO - Register worker addr: tcp://127.0.0.1:46397 name: 3
2026-11-10 09:19:25,899 - distributed.worker - INFO - Starting Worker plugin shuffle
2026-11-10 09:19:25,899 - distributed.scheduler - INFO - Starting worker compute stream, tcp://127.0.0.1:46397
2026-11-10 09:19:25,901 - distributed.worker - INFO - Registered to: tcp://127.0.0.1:35689
2026-11-10 09:19:25,901 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,901 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:41106
2026-11-10 09:19:25,901 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:35689
2026-11-10 09:19:25,902 - distributed.scheduler - INFO - Register worker addr: tcp://127.0.0.1:40655 name: 1
2026-11-10 09:19:25,903 - distributed.scheduler - INFO - Starting worker compute stream, tcp://127.0.0.1:40655
2026-11-10 09:19:25,903 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:41118
2026-11-10 09:19:25,904 - distributed.scheduler - INFO - Register worker addr: tcp://127.0.0.1:43819 name: 2
2026-11-10 09:19:25,903 - distributed.worker - INFO - Starting Worker plugin shuffle
2026-11-10 09:19:25,904 - distributed.worker - INFO - Registered to: tcp://127.0.0.1:35689
2026-11-10 09:19:25,904 - distributed.scheduler - INFO - Starting worker compute stream, tcp://127.0.0.1:43819
2026-11-10 09:19:25,904 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,904 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:35689
2026-11-10 09:19:25,905 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:41096
2026-11-10 09:19:25,905 - distributed.worker - INFO - Starting Worker plugin shuffle
2026-11-10 09:19:25,905 - distributed.worker - INFO - Registered to: tcp://127.0.0.1:35689
2026-11-10 09:19:25,905 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,906 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:35689
2026-11-10 09:19:25,907 - distributed.scheduler - INFO - Register worker addr: tcp://127.0.0.1:38667 name: 0
2026-11-10 09:19:25,907 - distributed.scheduler - INFO - Starting worker compute stream, tcp://127.0.0.1:38667
2026-11-10 09:19:25,907 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:41122
2026-11-10 09:19:25,908 - distributed.worker - INFO - Starting Worker plugin shuffle
2026-11-10 09:19:25,908 - distributed.worker - INFO - Registered to: tcp://127.0.0.1:35689
2026-11-10 09:19:25,908 - distributed.worker - INFO - -------------------------------------------------
2026-11-10 09:19:25,909 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:35689
2026-11-10 09:19:25,925 - distributed.scheduler - INFO - Receive client connection: Client-d2e8f2f7-dce7-11f1-8905-4676ccbaa09b
2026-11-10 09:19:25,925 - distributed.core - INFO - Starting established connection to tcp://127.0.0.1:41124
To view the Dask dashboard open this link in your browser: http://127.0.0.1:8787/status
+---------------------------------------------------------------------------------------------------+
| Simulation |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| self : <queens.models.simulation.Simulation object at 0x770e700cc680> |
| scheduler : <queens.schedulers.local.Local object at 0x770e70474680> |
| driver : <queens_interfaces.fourc.driver.Fourc object at 0x770e7031a810> |
+---------------------------------------------------------------------------------------------------+
+-------------------------------------------------------------------------------------------------------------+
| DeterministicOptimization |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| self : <queens.iterators.optimization.DeterministicOptimization object at 0x770e7010b3b0> |
| model : <__main__.LossFunction object at 0x770e67f41430> |
| parameters : <queens.parameters.parameters.Parameters object at 0x770e700cff50> |
| global_settings : <queens.global_settings.GlobalSettings object at 0x770e700e38f0> |
| initial_guess : [200, 0.4] |
| result_description : {'write_results': True} |
| verbose_output : False |
| bounds : Bounds(array([10, 0]), array([1.0e+04, 4.5e-01])) |
| constraints : None |
| max_feval : 1000 |
| algorithm : 'L-BFGS-B' |
| jac_method : '2-point' |
| jac_rel_step : None |
| objective_and_jacobian : True |
+-------------------------------------------------------------------------------------------------------------+
+---------------------------------------------------------------------------------------------------------+
| DeterministicOptimization |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| self : <queens.iterators.optimization.DeterministicOptimization object at 0x770e7010b3b0> |
| model : <__main__.LossFunction object at 0x770e67f41430> |
| parameters : <queens.parameters.parameters.Parameters object at 0x770e700cff50> |
| global_settings : <queens.global_settings.GlobalSettings object at 0x770e700e38f0> |
| result_description : {'write_results': True} |
+---------------------------------------------------------------------------------------------------------+
+---------------------------------------------------------------------------------------------------+
| git information |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| commit hash : cf8e531d09a5049bec8a3ad5858c6c338df0f9f9 |
| branch : main |
| clean working tree : False |
+---------------------------------------------------------------------------------------------------+
DeterministicOptimization for experiment: optimization_young_poisson_ratio
Starting Analysis...
Welcome to Optimization core run.
/__w/queens/queens/src/queens/iterators/optimization.py:318: OptimizeWarning: Unknown solver options: disp
self.solution = minimize(
67%|██████▋ | 2/3 [00:01<00:00, 1.24it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 0 - 2 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 1.863e+00s |
| average time per parallel job : 1.863e+00s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:01<00:00, 1.61it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[200. 0.4]
with intermediate values of the objective function
[270.85290426]
100%|██████████| 3/3 [00:01<00:00, 1.93it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 3 - 5 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 1.646e+00s |
| average time per parallel job : 1.646e+00s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:01<00:00, 1.82it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[192.96485958 0. ]
with intermediate values of the objective function
[101.9084566]
33%|███▎ | 1/3 [00:00<00:01, 1.42it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 6 - 8 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.720e-01s |
| average time per parallel job : 7.720e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 3.88it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[192.63505091 0. ]
with intermediate values of the objective function
[100.83344406]
33%|███▎ | 1/3 [00:00<00:01, 1.42it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 9 - 11 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.359e-01s |
| average time per parallel job : 7.359e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.07it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[191.31581623 0. ]
with intermediate values of the objective function
[96.60468867]
33%|███▎ | 1/3 [00:00<00:01, 1.36it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 12 - 14 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.805e-01s |
| average time per parallel job : 7.805e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 3.84it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[186.03887752 0. ]
with intermediate values of the objective function
[80.83038289]
33%|███▎ | 1/3 [00:00<00:01, 1.44it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 15 - 17 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.313e-01s |
| average time per parallel job : 7.313e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.10it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[143.06999551 0. ]
with intermediate values of the objective function
[20.32256677]
33%|███▎ | 1/3 [00:00<00:01, 1.45it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 18 - 20 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.299e-01s |
| average time per parallel job : 7.299e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.11it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[1.42356700e+02 2.24250186e-02]
with intermediate values of the objective function
[18.81837119]
33%|███▎ | 1/3 [00:00<00:01, 1.48it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 21 - 23 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.103e-01s |
| average time per parallel job : 7.103e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.22it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[1.39503519e+02 1.12125093e-01]
with intermediate values of the objective function
[13.09342272]
33%|███▎ | 1/3 [00:00<00:01, 1.43it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 24 - 26 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.401e-01s |
| average time per parallel job : 7.401e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.05it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[128.75639017 0.45 ]
with intermediate values of the objective function
[12.74797137]
33%|███▎ | 1/3 [00:00<00:01, 1.43it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 27 - 29 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.298e-01s |
| average time per parallel job : 7.298e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.11it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[138.33707717 0.14879642]
with intermediate values of the objective function
[10.88236446]
33%|███▎ | 1/3 [00:00<00:01, 1.41it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 30 - 32 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.533e-01s |
| average time per parallel job : 7.533e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 3.98it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[129.76606357 0.45 ]
with intermediate values of the objective function
[14.269165]
33%|███▎ | 1/3 [00:00<00:01, 1.41it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 33 - 35 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.422e-01s |
| average time per parallel job : 7.422e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.04it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[133.82708504 0.3072871 ]
with intermediate values of the objective function
[2.90870826]
33%|███▎ | 1/3 [00:00<00:01, 1.40it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 36 - 38 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.416e-01s |
| average time per parallel job : 7.416e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.04it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[116.36545374 0.45 ]
with intermediate values of the objective function
[2.74918278]
33%|███▎ | 1/3 [00:00<00:01, 1.43it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 39 - 41 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.329e-01s |
| average time per parallel job : 7.329e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.09it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[129.56218669 0.34214387]
with intermediate values of the objective function
[1.2536868]
33%|███▎ | 1/3 [00:00<00:01, 1.48it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 42 - 44 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.355e-01s |
| average time per parallel job : 7.355e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.08it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[120.31396943 0.45 ]
with intermediate values of the objective function
[4.19491644]
33%|███▎ | 1/3 [00:00<00:01, 1.45it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 45 - 47 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.514e-01s |
| average time per parallel job : 7.514e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 3.99it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[125.75154383 0.38658499]
with intermediate values of the objective function
[0.16099126]
33%|███▎ | 1/3 [00:00<00:01, 1.45it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 48 - 50 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.351e-01s |
| average time per parallel job : 7.351e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.08it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[120.31407207 0.40743051]
with intermediate values of the objective function
[0.18079805]
33%|███▎ | 1/3 [00:00<00:01, 1.44it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 51 - 53 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.343e-01s |
| average time per parallel job : 7.343e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.08it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[123.12252437 0.39666381]
with intermediate values of the objective function
[0.00898415]
33%|███▎ | 1/3 [00:00<00:01, 1.46it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 54 - 56 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.227e-01s |
| average time per parallel job : 7.227e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.15it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[122.77541063 0.40501085]
with intermediate values of the objective function
[0.02088685]
33%|███▎ | 1/3 [00:00<00:01, 1.48it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 57 - 59 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.155e-01s |
| average time per parallel job : 7.155e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.19it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[122.98363056 0.40000379]
with intermediate values of the objective function
[1.15983545e-05]
33%|███▎ | 1/3 [00:00<00:01, 1.47it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 60 - 62 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.215e-01s |
| average time per parallel job : 7.215e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.15it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[122.99965387 0.40000297]
with intermediate values of the objective function
[4.84507973e-09]
33%|███▎ | 1/3 [00:00<00:01, 1.43it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 63 - 65 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.359e-01s |
| average time per parallel job : 7.359e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.07it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[123.00002037 0.39999982]
with intermediate values of the objective function
[1.86543868e-11]
33%|███▎ | 1/3 [00:00<00:01, 1.43it/s]
+---------------------------------------------------------------------------------------------------+
| Batch summary for jobs 66 - 68 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| number of jobs : 3 |
| number of parallel jobs : 4 |
| number of procs : 1 |
| total elapsed time : 7.387e-01s |
| average time per parallel job : 7.387e-01s |
+---------------------------------------------------------------------------------------------------+
100%|██████████| 3/3 [00:00<00:00, 4.06it/s]
The intermediate, iterated parameters ['young', 'poisson_ratio'] are:
[122.9999999 0.39999999]
with intermediate values of the objective function
[6.51343474e-14]
Optimization took 1.913317E+01 seconds.
The optimum:
[122.9999999 0.39999999]
Time for CALCULATION: 19.13585066795349 s
2026-11-10 09:19:45,214 - distributed.scheduler - INFO - Retire worker addresses (stimulus_id='retire-workers-1794302385.2144284') (0, 1, 2, 3)
2026-11-10 09:19:45,215 - distributed.nanny - INFO - Closing Nanny at 'tcp://127.0.0.1:44399'. Reason: nanny-close
2026-11-10 09:19:45,215 - distributed.nanny - INFO - Nanny asking worker to close. Reason: nanny-close
2026-11-10 09:19:45,215 - distributed.nanny - INFO - Closing Nanny at 'tcp://127.0.0.1:41577'. Reason: nanny-close
2026-11-10 09:19:45,216 - distributed.nanny - INFO - Nanny asking worker to close. Reason: nanny-close
2026-11-10 09:19:45,216 - distributed.worker - INFO - Stopping worker at tcp://127.0.0.1:38667. Reason: nanny-close
2026-11-10 09:19:45,216 - distributed.nanny - INFO - Closing Nanny at 'tcp://127.0.0.1:41745'. Reason: nanny-close
2026-11-10 09:19:45,216 - distributed.worker - INFO - Removing Worker plugin shuffle
2026-11-10 09:19:45,217 - distributed.nanny - INFO - Nanny asking worker to close. Reason: nanny-close
2026-11-10 09:19:45,217 - distributed.nanny - INFO - Closing Nanny at 'tcp://127.0.0.1:38973'. Reason: nanny-close
2026-11-10 09:19:45,218 - distributed.nanny - INFO - Nanny asking worker to close. Reason: nanny-close
2026-11-10 09:19:45,219 - distributed.core - INFO - Received 'close-stream' from tcp://127.0.0.1:41122; closing.
2026-11-10 09:19:45,217 - distributed.core - INFO - Connection to tcp://127.0.0.1:35689 has been closed.
2026-11-10 09:19:45,217 - distributed.worker - INFO - Stopping worker at tcp://127.0.0.1:40655. Reason: nanny-close
2026-11-10 09:19:45,218 - distributed.worker - INFO - Removing Worker plugin shuffle
2026-11-10 09:19:45,218 - distributed.worker - INFO - Stopping worker at tcp://127.0.0.1:43819. Reason: nanny-close
2026-11-10 09:19:45,218 - distributed.worker - INFO - Removing Worker plugin shuffle
2026-11-10 09:19:45,218 - distributed.core - INFO - Connection to tcp://127.0.0.1:35689 has been closed.
2026-11-10 09:19:45,219 - distributed.worker - INFO - Stopping worker at tcp://127.0.0.1:46397. Reason: nanny-close
2026-11-10 09:19:45,219 - distributed.worker - INFO - Removing Worker plugin shuffle
2026-11-10 09:19:45,219 - distributed.core - INFO - Connection to tcp://127.0.0.1:35689 has been closed.
2026-11-10 09:19:45,220 - distributed.nanny - INFO - Worker closed
2026-11-10 09:19:45,220 - distributed.nanny - INFO - Worker closed
2026-11-10 09:19:45,221 - distributed.core - INFO - Received 'close-stream' from tcp://127.0.0.1:41118; closing.
2026-11-10 09:19:45,221 - distributed.nanny - INFO - Worker closed
2026-11-10 09:19:45,224 - distributed.scheduler - INFO - Remove worker addr: tcp://127.0.0.1:38667 name: 0 (stimulus_id='handle-worker-cleanup-1794302385.224302')
2026-11-10 09:19:45,223 - distributed.core - INFO - Connection to tcp://127.0.0.1:35689 has been closed.
2026-11-10 09:19:45,225 - distributed.nanny - INFO - Worker closed
2026-11-10 09:19:45,225 - distributed.scheduler - INFO - Remove worker addr: tcp://127.0.0.1:40655 name: 1 (stimulus_id='handle-worker-cleanup-1794302385.2256775')
2026-11-10 09:19:45,227 - distributed.core - INFO - Received 'close-stream' from tcp://127.0.0.1:41096; closing.
2026-11-10 09:19:45,231 - distributed.scheduler - INFO - Remove worker addr: tcp://127.0.0.1:43819 name: 2 (stimulus_id='handle-worker-cleanup-1794302385.2309594')
2026-11-10 09:19:45,231 - distributed.core - INFO - Received 'close-stream' from tcp://127.0.0.1:41106; closing.
2026-11-10 09:19:45,231 - distributed.scheduler - INFO - Remove worker addr: tcp://127.0.0.1:46397 name: 3 (stimulus_id='handle-worker-cleanup-1794302385.231967')
2026-11-10 09:19:45,233 - distributed.scheduler - INFO - Lost all workers
2026-11-10 09:19:45,673 - distributed.nanny - INFO - Nanny at 'tcp://127.0.0.1:41577' closed.
2026-11-10 09:19:45,676 - distributed.nanny - INFO - Nanny at 'tcp://127.0.0.1:41745' closed.
2026-11-10 09:19:45,686 - distributed.nanny - INFO - Nanny at 'tcp://127.0.0.1:44399' closed.
2026-11-10 09:19:45,702 - distributed.nanny - INFO - Nanny at 'tcp://127.0.0.1:38973' closed.
2026-11-10 09:19:45,703 - distributed.scheduler - INFO - Closing scheduler. Reason: unknown
2026-11-10 09:19:45,704 - distributed.scheduler - INFO - Scheduler closing all comms
[17]:
# Let's do a forward simulation of the optimal parameters:
fourc_driver.data_processor = None
fourc_driver.run(
inputs=parameters.sample_as_dict(optimum),
experiment_dir=Path.cwd(),
job_id="calibrated_value",
num_procs=1,
experiment_name=None,
)
def tensor_norm(tensor_data):
data = np.hstack(
(tensor_data.tolist(), tensor_data[:, 3:].tolist())
) # duplicate offdiagonal terms
return np.sqrt((data**2).sum(axis=1)).reshape(-1, 1)
def plot_tensor_norm(output_mesh, field_name, data, plotter, color_bar_title):
output_mesh[field_name] = data
plotter.add_mesh(
output_mesh,
scalars=field_name,
scalar_bar_args={
"title": color_bar_title,
"title_font_size": 15,
"label_font_size": 15,
},
)
plotter.add_axes(line_width=5)
plotter.camera_position = [
(1.1321899035097993, -6.851600196807601, 2.7649096132703574),
(0.0, 0.0, 0.2749999999999999),
(-0.97637930372977, -0.08995062285804697, 0.19644933366041056),
]
if pyvista_available:
output_mesh = pv.read("calibrated_value/output/output-vtk-files/structure-00001.pvtu")
output_calibrated_value = output_mesh["element_cauchy_stresses_xyz"]
difference = output_calibrated_value - experimental_elementwise_cauchy_stress.reshape(
-1, 6
)
relative_error = tensor_norm(difference) / tensor_norm(
experimental_elementwise_cauchy_stress.reshape(-1, 6)
)
plotter = pv.Plotter()
plot_tensor_norm(
output_mesh,
"relative",
relative_error,
plotter,
"Relative error of the Cauchy stress norm difference between calibrated value and experimental data\n",
)
plotter.add_text(
f"E={np.round(optimum[0], decimals=2)}, nu={np.round(optimum[1], decimals=2)}",
position="upper_right",
)
plotter.show()
We have successfully conducted a calibration of the Young’s modulus \(E\) and Poisson’s ratio \(\nu\)! The largest relative error
between calibrated model output and experimental data is \(< 1.7\cdot10^{-8}\).
This means we have a good state estimation, i.e., the model output matches the provided data! In fact, the data was not experimental at all, but was generated with \(E=123\) and \(\nu=0.4\), which the optimizer identified quickly.
Why QUEENS?#
Hide complexity in handling complex simulation codes:
Driver: make 4C callable via a Python function callScheduler: schedule and handle simulations in parallelModel: hide the scheduler and driver logic for the QUEENS user
Nested parallelism
Multiple processes per 4C run
Multiple parallel 4C runs at the same time
Modularity:
Switched from grid evaluation to optimization simply by changing the iterator
4C simulation model did not change!
Let’s play around#
Let your creativity flow and try out stuff.
Inspirations#
Change the parameter ranges
Look at the 4C input
Look at the driver outputs
Why did the simulations fail? (hint: two different reasons)
Plot the displacement field