bloc.reporting#

Calculation-note reporting — constraints, KPIs, adapters, orchestration.

Submodules#

Classes#

Constraint

A named pass/fail criterion for a scalar output variable.

ConstraintResult

Evaluation result for one Constraint.

Functions#

generate_calculation_note_excel(scenario_results, ...)

Generate a Calculation Note Excel workbook.

actual_flow_m3h(mdot_kg_s, rho_kg_m3)

Return actual volumetric flow [m³/h] at current gas conditions.

compute_quench_kpis(gas_hot, mdot_hot_kg_s, X_quench, ...)

Compute quench and post-quench volumetric flows from an adiabatic mix.

evaluate_constraints(outputs, constraints)

Evaluate constraints against the scalar outputs dict.

find_secondary_source(cfg, target_node_id, ...)

Return the STONE node config for the secondary injection reservoir.

normal_flow_m3h(mdot_kg_s, gas)

Return normal volumetric flow [Nm³/h] at 0 °C, 101 325 Pa (DIN 1343).

parse_constraints_from_config(export_cfg)

Parse the constraints list from an export configuration dict.

generate_calculation_note(base_yaml[, module, ...])

Run scenarios and generate an automated Calculation Note (Excel).

generate_calculation_note_stone(base_yaml[, ...])

Run STONE scenarios and generate Calculation Note Excel.

compute_spring_kpis(sim)

Compute SPRING engineering KPIs from a solved STONE Simulation.

compute_spring_quench_nodes(sim)

Return post-processing node specs for quench_gas and post_quench.

Package Contents#

bloc.reporting.generate_calculation_note_excel(scenario_results, output_path, title='SPRING Calculation Note', subtitle='Generated by Bloc', diagram_paths=None, yaml_files=None, header_comments=None, custom_input_categories=None, custom_output_categories=None, custom_input_variable_map=None, custom_output_variable_map=None, constraints=None)#

Generate a Calculation Note Excel workbook.

Parameters:
  • scenario_results (dict) – {scenario_id: {"inputs": dict, "outputs": dict, "metadata": dict}} where inputs are the YAML initial parameters and outputs is the res_dic from the simulation.

  • output_path (str or Path) – Where to write the .xlsx file.

  • title (str) – Title for the header.

  • subtitle (str) – Subtitle / description.

  • diagram_paths (dict or None) – {scenario_id: {"sankey": path, "network": path}}. If provided, diagrams are embedded as images.

  • yaml_files (list of str or None) – YAML file names used for this report (shown in header).

  • header_comments (list of str or None) – Header comments extracted from the YAML file (update log, etc.).

  • custom_input_categories (dict or None) – Override for bloc.yaml_utils.INPUT_CATEGORIES (e.g. tube furnace model).

  • custom_output_categories (dict or None) – Override for bloc.yaml_utils.OUTPUT_CATEGORIES.

  • custom_input_variable_map (dict or None) – Override for bloc.yaml_utils.INPUT_VARIABLE_MAP.

  • custom_output_variable_map (dict or None) – Override for bloc.yaml_utils.OUTPUT_VARIABLE_MAP.

  • constraints (list of bloc.constraints.Constraint or None) – Design constraints evaluated against each scenario’s outputs. When provided, a DESIGN CONSTRAINTS section is added to the summary sheet with red-background cells for violated constraints.

Returns:

The path to the generated file.

Return type:

Path

class bloc.reporting.Constraint#

A named pass/fail criterion for a scalar output variable.

Parameters:
  • key (str) – Key in the outputs dict (e.g. "Fo_D_min").

  • description (str) – Human-readable label shown in the Calculation Note.

  • operator (str) – Comparison operator: one of ">", "<", ">=" or "<=".

  • threshold (float) – Reference value the output must satisfy.

key: str#
description: str#
operator: Literal['>', '<', '>=', '<=']#
threshold: float#
criterion_str()#

Return a compact criterion expression, e.g. 'Fo_D_min > 1.0'.

class bloc.reporting.ConstraintResult#

Evaluation result for one Constraint.

Parameters:
  • constraint (Constraint) – The constraint that was evaluated.

  • value (float or None) – Actual value extracted from the outputs dict; None if the key was absent.

  • passed (bool or None) – True / False if the value is finite and available; None if the value is missing or NaN.

constraint: Constraint#
value: float | None#
passed: bool | None#
bloc.reporting.actual_flow_m3h(mdot_kg_s, rho_kg_m3)#

Return actual volumetric flow [m³/h] at current gas conditions.

Parameters:
  • mdot_kg_s – Mass flow rate [kg/s].

  • rho_kg_m3 – Gas density at actual (T, P) [kg/m³].

bloc.reporting.compute_quench_kpis(gas_hot, mdot_hot_kg_s, X_quench, T_cold_C, T_target_C, mech)#

Compute quench and post-quench volumetric flows from an adiabatic mix.

Calls bloc.reactors.optim.find_quench_flow() to determine the quench mass flow needed to reach T_target_C, then evaluates actual and normal volumetric flows for the quench stream and the mixed post-quench stream.

Parameters:
  • gas_hot – Cantera Solution at the pre-quench state (T_out, P, Y of hot gas). Not mutated.

  • mdot_hot_kg_s – Hot-gas mass flow rate [kg/s].

  • X_quench – Mole-fraction array or dict for the quench gas composition.

  • T_cold_C – Quench gas temperature [°C].

  • T_target_C – Target post-quench temperature [°C].

  • mech – Cantera mechanism file path (used to create temporary gas objects).

Returns:

Keys: "qm_quench_kg_s", "Q_quench_m3h", "Q_quench_N_m3h", "Q_post_quench_m3h", "Q_post_quench_N_m3h". Values are None when the quench calculation cannot be performed.

Return type:

dict

bloc.reporting.evaluate_constraints(outputs, constraints)#

Evaluate constraints against the scalar outputs dict.

Parameters:
  • outputs (dict) – Flat scalar dict (e.g. from _build_result or _tf_kpi_extractor).

  • constraints (list[Constraint]) – Constraints to evaluate.

Returns:

One result per constraint, in the same order as constraints.

Return type:

list[ConstraintResult]

bloc.reporting.find_secondary_source(cfg, target_node_id, excluded_source_ids)#

Return the STONE node config for the secondary injection reservoir.

Walks STONE connections to find any MassFlowController that feeds target_node_id from a source not in excluded_source_ids, then returns the matching node dict from nodes.

Parameters:
  • cfg – Parsed STONE YAML dict (top-level, containing connections and nodes).

  • target_node_id – Node id of the reactor receiving secondary injection (e.g. the PSR).

  • excluded_source_ids – Set of node ids to exclude (e.g. the torch ids).

Returns:

STONE node dict for the first matching secondary source, or None if none is found.

Return type:

dict or None

bloc.reporting.normal_flow_m3h(mdot_kg_s, gas)#

Return normal volumetric flow [Nm³/h] at 0 °C, 101 325 Pa (DIN 1343).

Uses bloc.chem.get_DIN1343_properties() to evaluate density at normal conditions without mutating gas.

Parameters:
  • mdot_kg_s – Mass flow rate [kg/s].

  • gas – Cantera Solution carrying the gas composition. Only the species composition is used; (T, P) are overridden internally.

bloc.reporting.parse_constraints_from_config(export_cfg)#

Parse the constraints list from an export configuration dict.

Reads export_cfg["constraints"], a list of dicts with keys key, description, operator, threshold.

Parameters:

export_cfg (dict or None) – Export configuration dict (from base_yaml["export"] or similar). If None or missing the "constraints" key, returns [].

Returns:

Parsed constraints; empty list if none defined.

Return type:

list[Constraint]

bloc.reporting.generate_calculation_note(base_yaml, module=None, output_dir='Results', extra_yamls=None, *, backend='ctwrap', kpi_fn=None, validate_strict=False)#

Run scenarios and generate an automated Calculation Note (Excel).

This is the unified entry point for Bloc’s Calculation Note generation. Two backends are supported:

  • backend="stone" (recommended) — YAML-only path using bloc.io.boulder_bridge.build_simulation_from_yaml(); no Python module needed. Accepts kpi_fn and validate_strict and forwards them to generate_calculation_note_stone().

  • backend="ctwrap" (deprecated) — legacy path that drives a ctwrap simulation module. Requires the module argument. Emits a DeprecationWarning. Port to STONE using docs/migration_guide.md and switch to backend="stone".

The function reads the export section of base_yaml to configure the report. Recognised keys inside export:

  • calc_note – output Excel filename (default: <stem>_Calculation_Note.xlsx)

  • title – report title row

  • subtitle – report subtitle row

  • main_species – number of top species by mole fraction (default 8, gas-phase only)

  • main_species_mass – number of top species by mass fraction (default 6, gas-phase only)

  • minimum_mole_fraction_balance – include species until cumulative mole fraction >= this (0–1, default 0.95); use 0 to disable

  • minimum_mass_fraction_balance – include species until cumulative mass fraction >= this (0–1, default 0.95); use 0 to disable

  • mandatory_species – species that must always appear

  • minimum_hydrogen_balance – target H balance threshold (0–1, default 0.95); species are added in descending order of H-atom contribution until the cumulative sum accounts for at least this fraction of total inlet H

  • minimum_carbon_balance – target C balance threshold (0–1, default 0.95); same logic as minimum_hydrogen_balance but for carbon atoms

  • reactor_kind – selects the variable-map set; supported values: "TubeFurnace" (TF maps from bloc.yaml_utils); omit or leave blank for the default SPRING maps.

Minimal export section example:

export:
  calc_note: "MyProject_Calculation_Note.xlsx"
  title: "Hydrogen Production Analysis"
  subtitle: "Baseline vs. Optimized Configuration"
Parameters:
  • base_yaml (str or Path) – Absolute or relative path to the base YAML configuration file.

  • module (module, optional) – Imported simulation module (from bloc.batch.import_simulation()). Required when backend="ctwrap"; ignored when backend="stone".

  • output_dir (str) – Sub-directory (relative to base_yaml’s parent) for output files.

  • extra_yamls (str, list[str], or None) – YAML files to use as overlay scenarios. Can be: - A glob pattern (e.g., "SPRING_A3_BG_20260212_gen*.yaml") - A list of file paths or glob patterns - None (default): only the base scenario is run (no overlay scenarios).

  • backend ({"stone", "ctwrap"}) – Which simulation backend to use (see above). Prefer "stone"; "ctwrap" is deprecated and will be removed in a future release.

  • kpi_fn (callable, optional) – STONE-only; forwarded to generate_calculation_note_stone().

  • validate_strict (bool) – STONE-only; forwarded to generate_calculation_note_stone().

Returns:

Path to the generated Excel file, or None if no export section was found in the YAML.

Return type:

Path or None

Raises:

None – If no export section is present in the YAML, the function returns None without raising an error.

bloc.reporting.generate_calculation_note_stone(base_yaml, output_dir='Results', extra_yamls=None, scenario_yamls=None, include_base=True, validate_strict=False, kpi_fn=None)#

Run STONE scenarios and generate Calculation Note Excel.

Uses bloc.io.boulder_bridge.build_simulation_from_yaml() for each scenario (base + overlays). Validates YAML with validate_yaml_file() (no strict unit check for STONE). Writes the same Excel format as generate_calculation_note().

Parameters:
  • base_yaml (str or Path) – Path to the base STONE YAML (e.g. SPRING_A3_BG_20260212_stone.yaml).

  • output_dir (str) – Output directory relative to the YAML parent.

  • extra_yamls (str or list[str] or None) – Glob pattern(s) for overlay STONE YAMLs (e.g. “_stone.yaml”). Deprecated — prefer declaring variations inline in the base YAML via scenarios: or sweeps: (see bloc.yaml_utils.expand_scenarios()). Combining inline scenarios with extra_yamls is rejected.

  • scenario_yamls (str or list[str] or None) – Standalone scenario YAML files/patterns to run and aggregate into the same workbook. Supports files using from: master.yaml inheritance. Unlike extra_yamls, these files are not deep-merged onto base_yaml; each is treated as a complete scenario definition.

  • include_base (bool) – If True, run the base YAML as a scenario in addition to inline/standalone scenarios. If False, base is used only as workbook/export template.

  • validate_strict (bool) – If True, raise on any YAML validation issue.

  • kpi_fn (callable or None) – Optional kpi_fn(sim) -> dict that computes domain-specific KPIs from each solved Simulation. Its output is merged into the outputs column of the Calculation Note. Equivalent to setting export.kpi_fn: "module:attr" in the YAML; specifying both is ambiguous and raises ValueError. Use bloc.reporting.spring_kpi.compute_spring_kpis() for SPRING architectures.

Notes

The STONE export: block also accepts:

  • kpi_fn — dotted path ("module:attr") resolved via bloc.yaml_utils.resolve_dotted().

  • figures — list of keys into bloc.yaml_utils.STONE_FIGURE_GENERATORS. Each generator has signature (sim, out_dir) -> dict[str, str].

Returns:

Path to the generated Excel file, or None if base YAML has no metadata.

Return type:

Path or None

bloc.reporting.compute_spring_kpis(sim)#

Compute SPRING engineering KPIs from a solved STONE Simulation.

This function bridges the STONE/Boulder path to produce the same outputs as simulation_non_isothermal_reactors.py (res_dic), so that both run_scenarios.py and run_yaml_scenarios.py generate the same Calculation Note Excel.

Reactors are located by walking sim.config['nodes'] (the STONE declaration) and pulling the first node of each expected type by id, then resolving it via sim.network.reactors (matched on .name). This is deterministic even when multiple reactors of the same Python class are present, unlike isinstance-based ordering. Input parameters are read from sim.config (nodes + connections).

Parameters:

sim (bloc.io.boulder_bridge.Simulation) – Solved STONE simulation returned by bloc.io.boulder_bridge.build_simulation_from_yaml().

Returns:

KPI dict with the same keys as the res_dic produced by simulation_non_isothermal_reactors.py. Unavailable values are omitted. Pass as kpi_fn to bloc.calc_note.generate_calculation_note_stone().

Return type:

dict

Notes

KPIs that depend on SPRING-specific YAML structure (e.g. node naming conventions, insulation parameters) are resolved by reactor type rather than by hard-coded node ID, making this function portable across STONE YAML variants that use the PlasmaTorchInstantaneousHeating/ContinuousMixingReactor/RefractoryReactor components.

bloc.reporting.compute_spring_quench_nodes(sim)#

Return post-processing node specs for quench_gas and post_quench.

These nodes are not part of the Cantera network; they are derived from the adiabatic quench mix computed in bloc.reporting.kpi.compute_quench_kpis() and injected into calc-note CSVs by bloc.calc_note._extract_node_data().

Returns:

Each dict has name, thermo (Solution), mass_flow_kg_s, and flow_role ("source" for the quench feed, "sink" for the terminal post-quench product).

Return type:

list[dict]