Skip to content

Module: tide.core

tide.core normalizes execution requests before a physics adapter runs. It provides one dispatch contract for TM2D and EM3D instead of allowing each solver family to interpret backend and fallback options independently.

Most application code does not need to call these functions directly. They are useful for configuration validation, capability inspection, and backend diagnostics.

flowchart TD
    A[User request] --> B[compile_simulation_plan]
    B --> C[SimulationPlan]
    C --> D[capability matrix]
    D --> E[select_backend]
    E --> F[BackendDecision]
    F --> G[Maxwell adapter]

compile_simulation_plan records dimension, derivative operation, model dtype and device, requested gradient targets, storage mode, callback use, component selection, batching, reference execution mode, and fallback policy.

from tide import compile_simulation_plan
plan = compile_simulation_plan(
operation="forward",
dimension="tm2d",
epsilon=epsilon,
storage_mode="device",
)

Physics-specific validation remains in the Maxwell layer. A valid plan does not prove that source coordinates, material values, CFL ratio, or component names are physically valid.

The normalized operation vocabulary is:

  • forward: nonlinear propagation.
  • jvp: tangent or Born action JvJv.
  • vjp: adjoint action JrJ^\top r.
  • second_vjp: nonlinear second-order action (DJ[v])r(DJ[v])^\top r.

Using derivative semantics rather than historical solver names lets capability rows describe the public operator API directly.

select_backend(plan, native_available=...) evaluates the requested plan against immutable capability rows. The resulting BackendDecision records selected backend, whether a fallback occurred, and the reason for an unsupported request.

from tide import select_backend
decision = select_backend(plan, native_available=True)
print(decision.selected)
print(decision.used_fallback)

A request for BackendPreference.NATIVE is never silently converted to another implementation when FallbackPolicy.ERROR is active. With FallbackPolicy.REFERENCE, selection may choose the reference backend only when that backend advertises the complete requested capability.

from tide.core.backends import backend_capabilities
capabilities = backend_capabilities(tide.BackendPreference.NATIVE)
for row in capabilities.matrix:
print(row.dimension, row.operations, row.storage_modes)

Each BackendCapability row covers:

  • Dimension.
  • Operation set.
  • CPU or CUDA device.
  • Float32 or float64 dtype.
  • Compute mode.
  • Snapshot storage modes.
  • Callback support.
  • Reusable background support.
  • Gradient targets.

The matrix is the executable source of truth. The rendered capability table is a readable snapshot and should be updated with code changes.

TypeImportant values
DimensionTM2D, EM3D
OperationFORWARD, JVP, VJP, SECOND_VJP
BackendPreferenceAUTO, REFERENCE, NATIVE
FallbackPolicyREFERENCE, ERROR
GradientTargetEPSILON, SIGMA, MU, PERTURBATION, SOURCE, STATE
StorageModeAUTO, DEVICE, CPU, DISK, NONE

SimulationPlan, BackendDecision, BackendCapability, and BackendCapabilities are immutable value objects. Treat them as diagnostic records, not mutable runtime configuration.

Without a central plan, one public entry point could silently fall back while another raises, or two solvers could interpret the same storage string differently. Central planning provides:

  • One operation vocabulary.
  • One fallback rule.
  • One capability table.
  • One place to test unsupported combinations.
  • Error messages that identify the rejected capability rather than failing inside a kernel.

New execution features must extend the plan and capability matrix before backend plumbing is added. This keeps unsupported cells explicit.