This guide maps the public model
workflow to the R and native subsystems that implement it. The supported
entry point is the GEModel reference-class generator. Call
its methods to load a TABLO model and data, configure a closure and
shocks, solve, and inspect results. Compiler, index, cache, and
source-data fields are implementation state; they are not supported
mutation inputs.
model = GEModelR::GEModel$new()
model$loadTablo("model.tab")
model$loadData(input_data, engine = "sparse")
model$setClosure("tax")
model$setShocks(setNames(4, 'tax["south"]'))
model$solveModel(engine = "sparse", backend = "Matrix")loadTablo() runs the TABLO parser and prepares both the
established R path and the sparse specification. The legacy path creates
R functions for data skeletons, coefficients, variables, and updates.
The sparse compiler turns supported equation and update forms into
indexed structures used by the sparse runtime.
loadData(engine = "legacy" or "sparse") initializes the
selected runtime; solveModel() must use that same engine.
The engine is the model runtime choice, while backend
selects an implementation within the sparse runtime.
| Responsibility | Main source files |
|---|---|
| Public orchestration and legacy solve loop | R/GEModel.R |
| TABLO statements and legacy generators | R/tabloToStatements.R, R/processTablo.R,
R/*Statement.R, R/*Generator.R |
| Sparse equation and update compilation | R/sparseCompiler.R |
| Sparse indexing, emission, solve acceptance, and diagnostics | R/sparseSolver.R, R/sparsePartition.R,
R/sparseElimination.R, R/sparseSchur*.R |
| Optional native capability checks and R adapters | R/zzzSparseSchurCpp.R,
R/zzzzSparseSchurOpenMP.R |
| Native sparse LU, Schur, and block-elimination kernels | src/sparse-lu.cpp, src/sparse-schur*.cpp,
src/sparse-elimination.cpp |
The sparse Matrix backend is the supported
general-purpose default. The structured R backends use a validated
partition when the model has the required structure. The experimental
C++ structured backend is an explicit capability choice: its preflight
checks the registered routines, ABI, Matrix factor contract, LAPACK, and
requested thread support before solving. A request that cannot run fails
capability checks; GEModelR does not silently substitute another
backend. SuiteSparse is recognized but unavailable in
supported installed builds. See the backend selection guide for the
user-facing choices and their current tiers.
Rcpp entry points are declared in the C++ sources and registered
through the generated R/RcppExports.R and
src/RcppExports.cpp files. Regenerate these wrappers with
Rcpp::compileAttributes(); do not edit generated wrappers
by hand. Native code checks dimensions, storage, and finite values
before use. OpenMP workers operate on prepared native buffers; R API
calls and R memory allocation stay on the main thread. Serial builds
remain supported.
Sparse triangular solves share one native kernel between serial and OpenMP execution. The kernel packs at most 32 right-hand sides into contiguous rows, then restores the caller’s matrix layout and permutations. Its temporary workspace is bounded by that tile width. Worker buffers are allocated before entering OpenMP, and worker failures are reported on the R thread. CSC storage and one-based positions are validated before native indexing; dense factor handles are tagged and released only by their owning implementation.
A sparse backend returns a candidate solution. Before that candidate is applied to model state, GEModelR checks its structure and finiteness and recomputes the true residual against the emitted full sparse system. A non-finite value, incompatible structure, or residual outside the configured tolerance rejects the candidate without applying it. This acceptance gate is shared across sparse backends; solver-specific diagnostics remain additional evidence rather than a replacement for the true-residual check.
Every solve attempt replaces model$lastDiagnostics with
a versioned outcome envelope. Setting diagnostics = TRUE
adds residual history, timings, allocation and capability evidence,
detailed cleanup status, and memory estimates. Solve-scoped backend
cleanup is recorded on success and failure. Native dense factors have
explicit release paths and finalizers. A post-simulation failure is
reported separately from numerical acceptance and can be retried with
retryPostsim() without another solve when the accepted
state is retained.
Small, deterministic parser and solver contracts belong in
tests/testthat/, with shared fixtures in
tests/testthat/fixtures/ and helpers in
tests/testthat/helper-*.R. The native CI workflow checks
installed solver contracts in serial builds on Linux, macOS, and
Windows, and OpenMP builds on Linux and Windows. The separate
benchmarks/ harnesses own larger performance and full-scale
comparisons; those runs use external inputs and do not belong in
ordinary package checks or documentation builds.