Metadata-Version: 2.4
Name: tgcalc
Version: 1.0.0
Summary: Expand Template-Goal-Calc TOML definitions into deduplicated concrete calc files.
Author: tgcalc contributors
License-Expression: MIT
Keywords: toml,workflow,parameters,sha256
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: mypy>=1.11; extra == "dev"
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Dynamic: license-file

# tgcalc

tgcalc expands Template-Goal-Calc TOML files into deduplicated concrete calc
files. It is a pure protocol library with zero dependencies.

## Core Protocol

- Template (`*.t.toml`): declares the parameters that a task type accepts.
- Goal (`*.g.toml`): multi-template experiment design with candidate values and
  grouping rules.
- Calc (`*.c.toml`): one concrete parameter set generated from a goal.

Calc filenames are based on the SHA256 digest of canonical JSON, not on the raw
TOML text. Comments, formatting, goal filename, descriptions, timestamps,
status, paths, and source metadata are intentionally excluded from the hash.

## Minimal Template

```toml
description = "A simple tensile simulation template"
version = "0.1.0"

[[parameters]]
name = "material"
description = "Material name"
type = "string"
unit = "dimensionless"

[[parameters]]
name = "temperature"
description = "Simulation temperature"
type = "number"
unit = "K"
```

Save this as `templates/model.t.toml`.

## Minimal Goal

```toml
[templates]
model = "model.t.toml"

[[value_groups]]
model.material = ["Au"]
model.temperature = [300]

[iter]
repeat = 2
```

Parameters in the same `[[value_groups]]` table are zipped by index. Different
value groups are crossed by Cartesian product. `iter.repeat` specifies how many
repetitions to generate (iter values 1, 2, ..., N). If `[iter]` is omitted,
tgcalc uses one default iteration.

## Generated Calc

One generated `*.c.toml` file looks like this:

```toml
[templates]
model = "model.t.toml"

[parameters]
model.material = "Au"
model.temperature = 300

[iter]
value = 1
```

The generated file name is `<sha256>.c.toml` by default.

## Python API

### Expand

```python
from tgcalc.core import expand_goal_file

results = expand_goal_file(
    "goals/size_effect.g.toml",
    template_dir="templates",
    output_dir="calcs",
    hash_len=16,
)

print(f"generated/reused {len(results)} calc files")
```

### Generate Input Files

```python
from tgcalc.inputs import template_function, generate_inputs

@template_function("model.t.toml")
def generate_model_inputs(model):
    with open("model.in", "w") as f:
        f.write(f"chemical_formula = {model.chemical_formula}\n")
        f.write(f"lateral_size = {model.lateral_size}\n")

@template_function("loading.t.toml")
def generate_loading_inputs(loading):
    with open("loading.in", "w") as f:
        f.write(f"strain_mode = {loading.strain_mode}\n")

generate_inputs(
    "calcs/abc123.c.toml",
    "inputs",
    bindings=[generate_model_inputs, generate_loading_inputs],
)
```

### Goal Validation

```python
from tgcalc.compat import check_template_goal_files

result = check_template_goal_files(
    "examples/basic/goals/size_effect.g.toml",
    template_dir="examples/basic/templates",
)

print(result.summary())
```

### Goal Index

```python
from tgcalc.index import build_goal_index

index = build_goal_index(
    "goals/size_effect.g.toml",
    template_dir="templates",
    hash_len=16,
)

# {
#   "abc123": {"model.height_layers": 3, "loading.strain_mode": "x"},
#   "def456": {"model.height_layers": 5, "loading.strain_mode": "y"},
# }
```

## Development

```bash
python -m pip install -e ".[dev]"
python -m pytest
python -m ruff check .
python -m mypy
```

## Documentation

| File | Purpose |
|------|---------|
| [`AGENTS.md`](AGENTS.md) | AI coding assistant instructions (Kilo, Cursor, Copilot) |
| [`docs/PROTOCOL.md`](docs/PROTOCOL.md) | Protocol layer specification |
| [`docs/TOML_PROTOCOL_GUIDE.md`](docs/TOML_PROTOCOL_GUIDE.md) | Detailed TOML format guide |
| [`CHANGELOG.md`](CHANGELOG.md) | Version history |

## Examples

The `examples/` directory contains runnable demonstrations of each feature.

### basic/ — Core protocol

Single-template workflow: template, goal, expand, calc files.

- `examples/basic/templates/two_dimensional_tensile.t.toml`
- `examples/basic/goals/size_effect.g.toml`

### template_handlers/ — Input generation

Multi-template workflow with `@template_function` and `generate_inputs`:

- `examples/template_handlers/templates/` — three templates (model, loading, simulation)
- `examples/template_handlers/goals/example.g.toml` — multi-template goal
- `examples/template_handlers/scripts/handlers.py` — template functions

### Standalone scripts

```bash
# Validate a goal against its templates
python examples/check_goal.py

# Expand a goal into calc files
python examples/expand_goal.py

# Generate input files for a calc
python examples/run_handlers.py
```
