scientific-workflow 0.1.0

Typed, template-defined system states for scientific workflows
Documentation
scientific-workflow-0.1.0 has been yanked.

scientific-workflow

scientific-workflow provides Rust primitives for representing scientific system states and building reproducible simulation workflows.

The crate currently focuses on SystemState: a fixed-layout, heterogeneous state container whose schema is loaded from JSON. Concrete payloads move into and out of a state without cloning, making the container suitable for large arrays and tensors used in scientific calculations.

Features

  • JSON-defined state fields with deterministic order and stable type tags.
  • Dictionary-like typed access to heterogeneous Rust payloads.
  • Clone-free payload insertion, in-place mutation, and owned extraction.
  • Explicit deep cloning of complete states.
  • Shared immutable state specifications.
  • Integer and optional finite physical time coordinates.
  • Strict template validation and semantic JSON round trips.
  • Compatibility with owned scientific payloads such as physics_in_parallel tensors.

Time-series storage, automatic chunking, and workflow dispatch are under active development and are not part of the published API described below.

Installation

Add the crate to a Rust project:

[dependencies]
scientific-workflow = "0.1"

The crate uses Rust edition 2024 and requires Rust 1.85 or newer.

State Template

A program begins with a JSON template that declares every state field:

{
  "fields": [
    {
      "name": "population",
      "type": "physics_in_parallel.tensor.dense.u64.v1"
    },
    {
      "name": "space",
      "type": "physics_in_parallel.tensor.dense.u64.v1"
    }
  ]
}

Field order defines the compact runtime slot order. The type value is a stable serialization tag rather than a Rust type name.

Basic Usage

use scientific_workflow::system_state::{StateSpec, TimePoint};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let spec = StateSpec::load("state.json")?;
    let mut state = spec.empty(TimePoint::new(0));

    state.set("population", vec![10_u64, 20, 30])?;

    state
        .get_mut::<Vec<u64>>("population")?
        .push(40);

    let population = state.take::<Vec<u64>>("population")?;
    assert_eq!(population, vec![10, 20, 30, 40]);
    assert!(state.is_blank());

    Ok(())
}

set consumes the supplied payload, and take returns that same owned payload. Neither operation calls Clone. Calling SystemState::clone explicitly deep-clones populated payloads so the two states can be mutated independently.

Tensor Payloads

Any concrete type satisfying Any + Clone + Send can be stored. For example, an application can use a dense physics_in_parallel tensor:

use physics_in_parallel::math::{Dense, Tensor};
use scientific_workflow::system_state::{StateSpec, TimePoint};

let spec = StateSpec::load("state.json")?;
let mut state = spec.empty(TimePoint::new(0));

let mut population = Tensor::<u64, Dense>::zeros(&[3]);
population.set(&[0], 10);
population.set(&[1], 20);
population.set(&[2], 30);

state.set("population", population)?;
let population = state.take::<Tensor<u64, Dense>>("population")?;

The tensor crate is not a required runtime dependency of scientific-workflow; applications select and register their own concrete scientific payload types.

Testing

From the package directory:

cargo test

The public integration suite loads an actual JSON template and exercises the complete state lifecycle using physics_in_parallel tensor payloads.

License

Licensed under the MIT License.