SPILSNet-Torch
A high-performance PyTorch implementation of SPILSNet (Spatiotemporal Physics-derived Internal Latent Space Network).
SPILSNet is designed for modeling complex dynamical systems where preserving physical structure (like spatial relationships and temporal consistency) is critical. It combines convolutional encoders for spatial feature extraction with a Gated Recurrent Unit (GRU) core to capture temporal evolution, while maintaining a learned skip-connection architecture to preserve high-frequency details.
Features
- Unified Non-Pickle Serialization: Industry-standard
safetensorsformat for weights and metadata (config, scalers), ensuring cross-platform safety and performance. - Graph Neural Network (PyG) Integration:
SPILSNetGrapharchitecture for handling 3D unstructured meshes and arbitrary domain interface topologies using Graph Convolutions (GraphSAGE / GCN). - Physics-derived Temporal Dynamics: GRU-based core for robust state-space modeling.
- Flexible Scaling: Built-in support for Scikit-learn scalers and custom transformers (e.g., CubeRoot).
- Professional Engineering: Full type hinting, Google-style docstrings, and robust serialization.
- Extensible Loss: Custom
spils_lossincluding Laplacian smoothness terms for spatial consistency.
Installation
Install via pip:
pip install spilsnet-torch
For development:
git clone https://github.com/andinoboerst/spilsnet-torch.git
cd spilsnet-torch
pip install -e ".[dev]"
Quick Start
1. Standard 2D Structured Model (Convolutional Encoder)
import numpy as np
import torch
from spilsnet import SPILSNet
from sklearn.preprocessing import StandardScaler
# 1. Configure the architecture
model_config = {
"dimension": 2, # 2D coordinates (x, y)
"input_size": 102, # 51 nodes * 2 dimensions
"internal_state_size": 16, # Size of physical internal states
"encoder_structure": [
{"out": 32, "k": 3, "s": 1, "p": 1},
{"out": 16, "k": 3, "s": 1, "p": 1},
],
"bottleneck_pool_size": 4,
"latent_dim": 32,
"gru_hidden_size": 64,
"latent_encoder_mlp": [64, 64],
"internal_input_mlp": [32],
"internal_output_mlp": [32],
"dropout_rate": 0.1,
}
# 2. Initialize the wrapper
model = SPILSNet(
model_config=model_config,
input_scaler_class=StandardScaler(),
internal_in_scaler_class=StandardScaler(),
internal_out_scaler_class=StandardScaler(),
output_scaler_class=StandardScaler()
)
# 3. Fit the model
# X: [Sims, Steps, Input_Size], Y: [Sims, Steps, Output_Size], I: [Sims, Steps, Internal_Size]
X, Y, I = np.random.randn(10, 50, 102), np.random.randn(10, 50, 102), np.random.randn(10, 50, 16)
model.fit(X, Y, I)
# 4. Sequential Inference
model.initialize_memory_variables()
current_x = np.random.randn(102)
next_y = model.predict(current_x)
print(f"Predicted next state shape: {next_y.shape}")
2. 3D Unstructured Mesh / Interface Model (Graph Neural Network Encoder)
import numpy as np
import torch
from spilsnet import SPILSNetGraph, connectivity_to_edge_index
from sklearn.preprocessing import StandardScaler
# 1. Define mesh element connectivity & node spatial coordinates
# connectivity shape: [Num_Elements, Nodes_Per_Element] (0-indexed node indices)
connectivity = np.array([
[0, 1, 2],
[1, 2, 3],
[2, 3, 4]
])
edge_index = connectivity_to_edge_index(connectivity)
# Optional: pass static node spatial coordinates [Num_Nodes, Coord_Dim] for GNN spatial awareness
node_coordinates = np.random.randn(50, 3)
# 2. Configure the GNN architecture
model_config = {
"dimension": 3, # 3D nodal state features (x, y, z)
"input_size": 150, # 50 nodes * 3 dimensions
"internal_state_size": 16,
"conv_type": "SAGE", # GraphSAGE ("SAGE") or GCN ("GCN")
"encoder_structure": [
{"out": 32},
{"out": 64},
],
"skip_target_nodes": 4,
"latent_dim": 32,
"gru_hidden_size": 64,
"latent_encoder_mlp": [64, 64],
"internal_input_mlp": [32],
"internal_output_mlp": [32],
"latent_decoder_structure": [256, 512],
"use_decoder_conv": True,
"dropout_rate": 0.1,
}
# 3. Initialize SPILSNetGraph (with optional node_coordinates)
model = SPILSNetGraph(
edge_index=edge_index,
node_coordinates=node_coordinates,
model_config=model_config,
input_scaler_class=StandardScaler(),
internal_in_scaler_class=StandardScaler(),
internal_out_scaler_class=StandardScaler(),
output_scaler_class=StandardScaler()
)
# 4. Fit the model
X = np.random.randn(10, 50, 150)
Y = np.random.randn(10, 50, 150)
I = np.random.randn(10, 50, 16)
model.fit(X, Y, I)
# 5. Sequential Inference
model.initialize_memory_variables()
current_x = np.random.randn(150)
next_y = model.predict(current_x)
print(f"Predicted next state shape: {next_y.shape}")
Testing
Run the test suite using pytest:
pytest
To run with coverage:
pytest --cov=spilsnet
License
This project is licensed under the AGPL 3.0 License - see the LICENSE file for details.
Citation
If you use this code in your research, please cite the associated paper and this repository.
Paper Citation
@article{boerst_2026_spilsnet,
title={Accelerating Transient Structural Dynamics via SPILS-Net, a Physics-Derived Latent Space Subdomain Surrogate},
author={Börst, Andino and Díez, Pedro and Zlotnik, Sergio and Cavaliere, Fabiola and Curtosi, Gabriel and Larráyoz, Xabier},
journal={Computer Methods in Applied Mechanics and Engineering},
year={2026},
doi={10.1016/j.cma.2026.119234}
}
Software Citation
(this repository, spilsnet-torch, available on PyPI):
@software{boerst_2026_spilsnet_torch,
author={Börst, Andino},
title={spilsnet-torch: PyTorch Implementation of SPILS-Net},
year={2026},
publisher={Zenodo},
url={https://doi.org/10.5281/zenodo.21236780},
doi={10.5281/zenodo.21236780},
version={1.1.0}
}
For machine-readable citation metadata, see CITATION.cff.
Metadata
Release files for spilsnet-torch 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| spilsnet_torch-1.1.0.tar.gz | 60.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| spilsnet_torch-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 105.3 kB
Release files / spilsnet_torch-1.1.0.tar.gz
| Download URL | spilsnet_torch-1.1.0.tar.gz |
|---|---|
| Size | 60.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
584ad06c3a5ef0ae2c8d737c6278016a3c9dc77bd33c35abd5b0c55e709da708
|
|
BLAKE2b-256 checksum How to use checksums |
55e8a000317609937631e6b69c72795208468653abeb6e4f76bc9dcbdb134467
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.
Transparency logRelease files / spilsnet_torch-1.1.0-py3-none-any.whl
| Download URL | spilsnet_torch-1.1.0-py3-none-any.whl |
|---|---|
| Size | 45.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1a0c653dddc61f4f58b812f96b70e8a14881a850390283384cde1ca7b651ebdc
|
|
BLAKE2b-256 checksum How to use checksums |
9c615e8b37ae14ba30edf9c8101fd8e8ce7993af5d76006c1e7c4dbb67baf68c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.
Transparency log