Architecture and dependency rules
The central architectural rule is simple:
Scientific results must not depend on the frontend that requested them.
The Python API, Click CLI, and a future GUI must call the same normalized
workflows and obtain the same float64 arrays.
Layered package model
external files
|
v
quantas.interfaces ------+
| |
v |
normalized contracts |
| |
v |
quantas.modules ----------+----> ResultData / HDF5
| |
+----------+-----------------------+
|
+----------+-----------+
| |
v v
quantas.api report / plot specs
| |
+----------+-----------+
|
+--------+--------+
| |
v v
quantas.cli future GUI/notebook
quantas.coreReusable scientific algorithms and policies. Core code does not know which module or frontend called it.
quantas.modelsShared passive containers and small active base contracts. This layer has no module-specific scientific policy.
quantas.interfacesCode-specific parsing. Interfaces convert external syntax to explicit physical quantities and provenance; they do not run Quantas workflows.
quantas.modulesScientific orchestration. A module validates normalized input, calls core routines, assembles typed results, emits events, persists payloads, builds reports and plot specifications, and exports data.
quantas.apiStable application-facing facades. Applications use this layer instead of concrete calculators, readers, or exporters.
quantas.renderersConcrete presentation of neutral tables and plots.
quantas.cliClick adapters and Rich terminal behaviour. The CLI parses and validates user input, constructs public options, calls
quantas.api, observes events, and renders the returned neutral objects.
Allowed dependency direction
A lower layer must not import a higher layer. The intended direction is:
core <- models <- interfaces/modules <- api <- cli or external application
|
+-> neutral report/plot models -> renderers
Important consequences are:
corenever importsmodules,interfaces,renderers, orcli;one scientific module does not import another module directly;
cross-module transformations belong in
quantas.api.interopor a shared lower-level contract, not in an accidental module-to-module import;interface parsers do not import workflows;
module plot builders import neutral plot contracts, not Matplotlib;
the CLI calls public API functions rather than concrete calculators.
The architecture tests enforce these boundaries by inspecting imports.
Active objects and passive data
Use a normal class for an object that owns behaviour, state, or a lifecycle:
calculators;
readers and exporters;
observers;
workflow controllers;
numerical solvers;
persistent EOS sessions.
Use a dataclass for passive information:
normalized inputs;
options;
metadata;
scientific results;
report and plot specifications;
immutable requests and diagnostics.
A useful test is: if the object performs I/O, emits events, advances through stages, or mutates internal state, it is probably not a passive dataclass.
Scientific module isolation
Modules share core physics and common contracts but remain independent. QHA must not import Thermoelasticity merely because Thermoelasticity consumes QHA results. SEISMIC must not be hidden inside Elasticity merely because both use elastic tensors.
This separation preserves:
independent scientific testing;
explicit transformations between domains;
smaller import surfaces;
reuse by frontends;
the ability to replace one workflow without destabilizing another.
Precision and units
The authoritative numerical policy is defined in
quantas.core.numerics.precision:
real calculations:
numpy.float64;complex calculations:
numpy.complex128;native HDF5 floating values:
float64;no runtime precision option.
Input units are normalized at workflow boundaries. Core functions should state and test the units they consume and return. Display precision and display-unit selection belong to reports, exporters, and renderers; they must never round or rescale the stored scientific arrays in place.
Error and warning ownership
Use exceptions for states in which the requested result cannot be interpreted safely. Use warnings for completed calculations that require scientific attention. Do not silently clip, repair, reorder, or extrapolate data unless the workflow explicitly defines that policy and records it in results or masks.
Frontend ownership
The CLI owns:
command names and option grouping;
string-to-type conversion;
prompts and overwrite confirmation;
output-path conventions;
Rich warnings, errors, progress, and tables.
The scientific workflow owns:
validation of scientific meaning;
numerical defaults and approximations;
warnings and failure policies;
result fields and masks;
report and plot data.
A future GUI may choose a different visual layout, but it must not reimplement or bypass the scientific decisions in the workflow.