Code for the article
A. Lucchetti, F. Cadini, M. Giglio, L. Lomazzi. Graph Network-based Structural Simulator: Graph Neural Networks for Structural Dynamics. Engineering with Computers, 2026. https://doi.org/10.1007/s00366-026-02451-w
GNSS is a graph neural network surrogate for dynamic structural problems. It follows the encode-process-decode scheme of the Graph Network-based Simulator (GNS) of Sanchez-Gonzalez et al. (2020), with three design choices: node kinematics in node-fixed local frames, a sign-aware regression loss (wMSE) and a wavelength-informed connectivity radius. The code was developed from the PyTorch implementation geoelements/gns; see THIRD_PARTY_NOTICES.md for the attribution.
The datasets, the finite element models and the trained checkpoints of every run reported in the article are in the Zenodo record https://doi.org/10.5281/zenodo.21704541.
conda env create -f environment.yml
conda activate gnssPython 3.10, PyTorch 2.4.1 (CUDA 12.1) and PyTorch Geometric 2.6.1. A CUDA GPU is required for training and evaluation.
Download the zip files of the Zenodo record and unzip them in the root of this repository:
| File | Content | Unzips to |
|---|---|---|
datasets.zip |
the five datasets read by the configs | datasets/ |
checkpoints.zip |
trained model, config.yaml and training log of every reported run |
experiments/ |
legacy.zip |
checkpoints and data of the archived original implementation (Figs. 3 to 5) | legacy/ |
fe_models.zip |
Abaqus/Explicit input decks of the beam and plate simulations | fe_models/ |
Train a model; the configuration is configs/experiments/<exp>.yaml, the run is written to
experiments/<exp>/<date>_<time>_<commit>/ and the test trajectory is rolled out at the end:
python main.py --mode=train --exp=thesisRoll out a trained model on the split set in its config.yaml (eval.split); the predictions are
written to <run>/predictions/model-<epoch>/<split>/<trajectory>.pkl:
python main.py --mode=eval --run_dir=experiments/thesis/example_run --regen_pklCompute the physical metrics (wave speed, phase lag, spectral L2, energy and displacement errors)
of every rollout of a run; they are written next to each .pkl and summarised in
<run>/predictions/physical_metrics_summary.json:
python scripts/eval_physical_metrics.py --run_dir=experiments/thesis/example_runThe beam metrics use the transverse component --component_axis 1 (default); the plate uses
--component_axis 2.
Each reported run is a folder of checkpoints.zip, trained with the config of the same name in
configs/experiments/. To reproduce a table or figure, roll out the run (main.py --mode=eval ... --regen_pkl), compute its metrics (scripts/eval_physical_metrics.py) and run the script
listed below.
| Item | Run folder in experiments/ |
Script |
|---|---|---|
| Table 1 | FE models in fe_models.zip |
|
| Table 2 | thesis_isl6_rerun/2026-09-08_11-43-14_7a17af8, thesis_ds5_sched/2026-09-09_12-25-57_25edfe5 |
metrics |
| Table 3 | thesis_isl6_rerun/2026-09-08_11-43-14_7a17af8, thesis_isl2/2026-09-08_11-31-17_6350af4 |
metrics, logs/training.log |
| Table 4 | thesis_rm_r*_m*[_s1,_s2]/* (45 runs) |
scripts/rm_grid/collect.py, scripts/rm_grid/summarize.py |
| Table 5, Table A1 | thesis/example_run |
metrics, logs/training.log |
| Table 6 | plate_light/2026-05-10_10-25-20_cfffbfa |
metrics with --component_axis 2 |
| Table 7, Fig. S8 | thesis_freqs_dense_noise0035_oob_eval/2026-09-07_eval-of-025d541-model-102 |
scripts/plot_freq_oob.py |
| Table 8 | thesis/example_run and the five thesis_lstm* runs |
scripts/aggregate_metrics_table.py |
| Figs. 3 to 5 | archived original implementation | see legacy/README.md |
| Fig. 6 | thesis/example_run |
scripts/plot_spectrogram.py --nodes 5 92 180 --freq_max_khz 160 |
| Fig. 7 | thesis/example_run |
scripts/plot_energy_snapshots.py |
| Fig. 8 | plate_light/2026-05-10_10-25-20_cfffbfa |
scripts/plot_plate_results.py |
| Fig. 9 | thesis_freqs_dense_noise0035/2026-05-05_18-44-47_025d541 |
scripts/plot_freq_rollout.py |
| Fig. 10 | thesis_freqs_dense_noise0035/2026-05-05_18-44-47_025d541 |
scripts/plot_spectrogram.py --trajectory Excitation_position_05_100kHz_1cyc |
| Computational cost | thesis/example_run |
scripts/time_inference.py --n_warmup 2 --n_timed 7 |
All scripts take --run_dir=experiments/<run folder>. Figs. 1, 2 and S1 to S7 are schematics.
Notes:
- Table 4:
bash scripts/rm_grid/run_grid.shretrains the 45 runs. To score the released checkpoints instead, roll out and compute the metrics of each run, then runcollect.pyandsummarize.py. - Table 7 and Fig. S8: the run folder holds the checkpoint of the seven-frequency model
(
thesis_freqs_dense_noise0035) with aconfig.yamlthat points to the evaluation datasetthesis_freqs_oob_eval_25a8c3db. - Table 8: the rows marked with a dagger use the validation-best checkpoints of the LSTM runs,
rolled out with
--checkpoint=<run>/models/secondary/model-best-val.pt. Their predictions go topredictions/model-model-best-val-<epoch>/; select them with--model_tag best-val, and the other rows with--exclude_model_tag best-val, inaggregate_metrics_table.py. The rows h = 128, l = 2 come fromthesis_lstm(no dagger) andthesis_lstm_sym(dagger). The check on the training trajectories usesthesis_lstm_h128_l3witheval.split: trainin itsconfig.yaml.
main.py training and evaluation entry point
src/ models, data loading, training and rollout loops, metrics
configs/experiments/ configuration of every reported run (rm_grid/: Table 4)
configs/trajectories/node_IDs.yaml node-type ids of the datasets
scripts/ evaluation, plotting and timing scripts
legacy/ archived original implementation (Figs. 3 to 5)
MIT, see LICENSE. Parts of the code derive from geoelements/gns (MIT License) and from DeepMind's learning_to_simulate (Apache License 2.0); see THIRD_PARTY_NOTICES.md. The data in the Zenodo record are released under CC BY 4.0.
Please cite the article above; see CITATION.cff.