Skip to content

Dataset schema

Schema v4 is selection-driven. Every dataset records a non-empty set of typed `Record` leaves instead of requiring a complete copy of the simulation result.

Record selector tree

record is required by generate_dataset(). The complete public selector tree is:

Record
├── signal                                  -> signal
├── clean_signal                            -> clean_signal
├── response
│   ├── displacement                        -> response/displacement
│   ├── velocity                            -> response/velocity
│   └── acceleration                        -> response/acceleration
├── system_parameter
│   ├── mass_matrix                         -> system/mass_matrix
│   ├── damping_matrix                      -> system/damping_matrix
│   └── stiffness_matrix                    -> system/stiffness_matrix
├── modal_parameter
│   ├── frequencies_hz                      -> modal/frequencies_hz
│   └── mode_shapes                         -> modal/mode_shapes
├── load
│   ├── force                               -> load/force
│   └── values                              -> load/values
├── metadata
│   ├── seed                                -> metadata/seed
│   └── generation                          -> dataset-level provenance
├── case_parameter                          -> parameters/<normalized case name>
├── time                                    -> time
└── positions                               -> positions

Family objects such as Record.response and Record.modal_parameter are namespaces only. They do not expand to all children and cannot be passed in record; select each required leaf. Record.case_parameter is one leaf with dynamic contents: it selects all numeric entries in the final case mapping. Duplicate fields and an empty selection are rejected.

Shapes of recorded arrays

Let N be samples, S sensors, T time points, D generalized coordinates, M modes, and P reporting positions. Only selected paths exist.

Path Shape
time (T,)
positions (P,)
signal (N, S, T)
clean_signal (N, S, T)
response/displacement (N, D, T)
response/velocity (N, D, T)
response/acceleration (N, D, T)
system/mass_matrix (N, D, D)
system/damping_matrix (N, D, D)
system/stiffness_matrix (N, D, D)
modal/frequencies_hz (N, M)
modal/mode_shapes (N, M, P)
load/force (N, D, T)
load/values (N, P, T)
metadata/seed (N,)
parameters/<normalized name> (N, *case_value.shape)

time and positions are shared coordinates without a sample dimension. All sample-scoped arrays have a leading N dimension, and every recorded path has a stable shape across samples. load/values is the rasterized diagnostic field on positions. For point and moving loads, load/force is projected from exact coordinates and need not equal a projection of that diagnostic raster.

Storage dtype

Simulation calculations and the complete SimulationResult remain float64. After a simulation finishes, DynaResp filters the result to the requested fields and casts recorded floating arrays to storage_dtype. The default is np.float64; use storage_dtype=np.float32 for compact in-memory and Zarr datasets.

The cast applies to selected signals, responses, matrices, modal data, loads, floating case values, time, and positions. Integer case values preserve their values in normalized int64 arrays, and metadata/seed remains uint64. Field selection reduces retained storage, not solver work or its temporary memory requirements.

Parameter and target names

When Record.case_parameter is selected, case names are normalized for storage:

Case name Parameter path Target name
masses parameters/masses masses
load.rms parameters/load_rms load.rms
stiffness_reduction parameters/stiffness_reduction stiffness_reduction

Parameter arrays preserve each sampled value's shape after the leading sample dimension. parameter_keys and target_keys retain their respective logical names, and both mappings reference the same stored arrays. No duplicate target/ arrays are written.

Dataset metadata

Every schema-v4 dataset stores the structural bookkeeping needed to validate its partial contents:

  • schema version and sample count;
  • selected record paths and storage dtype;
  • logical parameter and target mappings;
  • stored array keys.

Selecting Record.metadata.generation additionally stores the DynaResp version, root seed, builder identities, sensor definitions, variability provenance, and concrete system and load definitions for the first realization. Selecting Record.metadata.seed separately stores the effective seed for each sample. Axes are arrays only when their respective selectors are present; generation metadata does not duplicate omitted axes.

Schema v4 intentionally has no schema-v3 compatibility path. StructuralDataset.open() rejects stores with another schema version, so older datasets must be regenerated or migrated outside DynaResp.

Partial StructuralSample views

Indexing materializes only recorded values:

View When omitted
signal, clean_signal, time, positions None
target Empty unless Record.case_parameter was selected
system, modal, load Partial or empty dictionaries
metadata["parameters"] Absent unless case parameters were selected
generation and per-sample seed metadata Present only when selected

sample.metadata always identifies the sample index. Accessing a missing dataset-level property such as dataset.signal or dataset.time raises a clear KeyError. Adapters likewise raise KeyError when asked for an unrecorded input, target, or extra field.

sample = dataset[0]
print(sample.signal)
print(sample.modal["frequencies_hz"])
print(sample.target["temperature_c"])

Zarr storage behavior

Zarr output mirrors only the selected path tree as nested groups and arrays. Sample chunks contain at most 32 records. A new dataset is written to a temporary sibling and moved into place only after writing and validation succeed. Failed writes remove the temporary store and never leave a partial destination; an existing destination is not overwritten. Opening validates metadata, selected axes, and cross-array shapes without materializing sample tensors.