Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

219 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Metis 🎭

Documentation Metis CI Clang-Format Check codecov

Metis is a C++20 header-only numerical framework that implements a dual-mode code-transformations paradigm inspired by AeroSandbox. You write physics models once using generic templates; the same code compiles to optimized native arithmetic (Eigen) for simulation and builds a symbolic computational graph (CasADi) for automatic differentiation and gradient-based optimization. No code duplication, no runtime dispatch overhead.

Building & Development

Prerequisites

Recommended: Nix with flakes enabled -- the flake.nix pins every dependency.

Manual: CMake 3.20+, a C++20 compiler (Clang recommended), Eigen 3.4+, CasADi, GoogleTest, Ninja.

Dev environment

# Enter the Nix dev shell (sets up compiler, Eigen, CasADi, gtest, ccache, doxygen, lcov, etc.)
nix develop

# Or use the convenience wrapper
./scripts/dev.sh

Build, test, run

./scripts/build.sh              # CMake + Ninja debug build
./scripts/build.sh --release    # Release build
./scripts/test.sh               # Build (if needed) + ctest
./scripts/coverage.sh           # Build with coverage, run tests, generate lcov report
./scripts/run_examples.sh       # Build and run all 30 example programs
./scripts/verify.sh             # Full pre-push check: build + test + examples

Formatting is enforced via treefmt (clang-format, cmake-format, nixfmt):

nix fmt                         # Format everything
./scripts/install-hooks.sh      # Install pre-commit formatting hook

Project Structure

metis/
β”œβ”€β”€ docs/                        # Documentation
β”‚   β”œβ”€β”€ user_guides/             # 18 topic guides (see Documentation below)
β”‚   β”œβ”€β”€ patterns/                # Reusable patterns (branching, loops, hybrid optimization)
β”‚   └── design_overview.md       # Architecture deep-dive
β”œβ”€β”€ examples/                    # 30 runnable demos
β”‚   β”œβ”€β”€ intro/                   # Getting started (numeric, energy, sparsity, printing)
β”‚   β”œβ”€β”€ math/                    # Branching, graphs, loops, sensitivity, PCE, structural analysis
β”‚   β”œβ”€β”€ interpolation/           # N-D tables, scattered interpolation, root finding, file-based tables
β”‚   β”œβ”€β”€ simulation/              # ODE integration, drag, brachistochrone, hybrid, attitudes
β”‚   └── optimization/            # Rosenbrock, drag, beam, brachistochrone, sweeps, transcription comparison
β”œβ”€β”€ include/
β”‚   └── metis/
β”‚       β”œβ”€β”€ core/                # Type system, concepts, diagnostics, sparsity, structural analysis, IO
β”‚       β”œβ”€β”€ math/                # Trig, calculus, autodiff, interpolation, integration, root finding,
β”‚       β”‚                        #   quadrature, PCE, linalg, quaternions, rotations, surrogates
β”‚       β”œβ”€β”€ optimization/        # Opti interface, scaling, collocation, multiple shooting,
β”‚       β”‚                        #   pseudospectral, Birkhoff pseudospectral
β”‚       β”œβ”€β”€ utils/               # Utility helpers (JSON)
β”‚       β”œβ”€β”€ metis.hpp            # Main umbrella include
β”‚       └── using.hpp            # Convenience aliases/imports
β”œβ”€β”€ scripts/                     # Build, test, CI, coverage, formatting, doc generation
β”œβ”€β”€ tests/                       # GoogleTest suites (core/, math/, optimization/)
β”œβ”€β”€ CMakeLists.txt
└── flake.nix                    # Nix dev environment and package definition

Architecture Overview

Metis is built on a template-first traceability paradigm. User models are templated on a generic scalar type; the framework provides two backends that satisfy the same concept constraints. The numeric backend maps to double and Eigen::MatrixXd -- the compiler generates assembly identical to hand-written C++. The symbolic backend maps to casadi::MX and Eigen::Matrix<casadi::MX> -- the same code constructs a static computational graph suitable for automatic differentiation, sparsity detection, and NLP solvers.

A dispatch layer in the metis:: namespace shadows std:: math functions and uses C++20 concepts to route calls (metis::sin, metis::pow, etc.) to the correct backend at compile time. The framework draws a strict line between structural logic (integers, booleans, loop bounds -- these shape the graph) and value logic (floating-point quantities that flow through the graph). Standard if/else cannot branch on symbolic values; metis::where(condition, true_val, false_val) compiles to a ternary in numeric mode and a casadi::if_else switch node in symbolic mode.

For the full design rationale, see docs/design_overview.md.

Documentation

Organization

  • docs/user_guides/ -- 18 standalone guides, each covering one subsystem end-to-end.
  • docs/patterns/ -- Reusable coding patterns (branching, loops, hybrid optimization).
  • docs/design_overview.md -- Architecture principles and type system.
  • Doxygen API docs -- Generated from source comments.

Generating docs

./scripts/generate_docs.sh      # Or: doxygen Doxyfile

Hosted on GitHub Pages.

User guides

Guide Description
numeric_computing Numeric backend basics -- templates, Eigen, optimized machine code
symbolic_computing Symbolic backend -- CasADi graph construction, derivatives, code generation
math_functions Dispatch layer and ADL for dual-mode math (metis::sin, metis::pow, etc.)
interpolation N-dimensional gridded interpolation in numeric and symbolic modes
integration ODE solvers -- RK4, RK45, Stormer-Verlet, mass-matrix, second-order systems
root_finding Newton-Raphson and bracketing solvers with globalization
optimization metis::Opti interface for constrained NLP (IPOPT/SNOPT/QPOASES)
collocation Direct collocation transcription for optimal control
multiple_shooting Multiple shooting transcription via CasADi integrators (CVODES/IDAS)
pseudospectral Global polynomial pseudospectral transcription
birkhoff_pseudospectral Birkhoff-form pseudospectral with derivative collocation
transcription_methods Comparison and selection guide for all transcription methods
graph_visualization Visualizing computational graphs for debugging
polynomial_chaos Polynomial chaos expansion for uncertainty quantification
stochastic_quadrature Probability-measure quadrature rules for PCE workflows
sparsity Jacobian/Hessian sparsity detection and exploitation
structural_transforms Alias elimination and BLT decomposition for residual systems
structural_diagnostics Structural observability analysis for state estimation

Features

  • 🎭 Dual-Mode Physics: Write once, run as Numeric (Fast C++) or Symbolic (CasADi Graph).
  • πŸ”’ Unified Math: Std/CasADi agnostic math functions (metis::sin, metis::pow, metis::where).
  • ⚑ Linear Algebra: Eigen-based matrix operations compatible with symbolic types, policy-driven linear solvers.
  • πŸ“‰ Optimization: High-level Opti interface for NLP solvers (IPOPT/SNOPT/QPOASES) with Direct Collocation, Multiple Shooting, Pseudospectral, and Birkhoff Pseudospectral transcriptions. Variable/constraint scaling diagnostics, parametric sweeps.
  • πŸ” Differentiation: Automatic differentiation (Forward/Reverse) via CasADi, sparse Jacobian/Hessian pipelines, sensitivity regime selection, matrix-free HVPs.
  • ⏱️ Integration: ODE solvers (solve_ivp), Runge-Kutta methods, Stormer-Verlet (symplectic), second-order and mass-matrix integrators, discrete integration.
  • πŸ“ˆ Interpolation: 1D, 2D, Sparse, and N-D table lookups with B-spline support.
  • πŸ“ Geometry: Quaternions, Rotation Matrices, Euler Angles.
  • πŸ” Root Finding: Multi-method globalization stack (trust-region, line-search, Broyden, pseudo-transient), implicit function builders.
  • 🧠 Surrogates: Differentiable approximations (sigmoid, softmax, smooth abs/max/min/clamp) for discontinuous functions.
  • πŸ“Š Stochastic Analysis: Polynomial chaos expansion, stochastic quadrature (Gauss, Clenshaw-Curtis, Smolyak sparse grids).
  • πŸ”¬ Structural Analysis: Sparsity detection, alias elimination, BLT decomposition, structural observability/identifiability analysis.
  • πŸ’Ύ IO: Graph visualization, serialization, HTML export.

Examples

The examples/ directory contains 30 runnable demos organized by topic:

  • intro/ (4) -- Numeric basics, energy model, sparsity intro, printing
  • math/ (10) -- Branching logic, graph visualization, loops, sensitivity, PCE, linear solve policies, structural analysis
  • interpolation/ (4) -- N-D tables, scattered data, root finding, file-based table loading
  • simulation/ (5) -- Drag model, brachistochrone, hybrid systems, aircraft attitudes, smooth trajectories
  • optimization/ (6) -- Rosenbrock, drag optimization, beam deflection, brachistochrone, parametric sweeps, transcription comparison
  • integration (1) -- RK4, RK45, Stormer-Verlet, mass-matrix integrators

Build and run all examples:

./scripts/run_examples.sh

Quick Look

Write a model once, evaluate it numerically and symbolically:

#include <metis/metis.hpp>

// Generic model -- works with double or CasADi symbolic types
auto drag(auto rho, auto v, auto S, auto Cd) {
    return 0.5 * rho * metis::pow(v, 2) * S * Cd;
}

int main() {
    // Numeric mode -- compiles to native arithmetic
    double D = drag(1.225, 50.0, 10.0, 0.02);

    // Symbolic mode -- same function builds a CasADi graph
    metis::Opti opti;
    auto v = opti.variable(50.0);
    auto D_sym = drag(1.225, v, 10.0, 0.02);

    opti.minimize(D_sym);
    opti.subject_to_bounds(v, 10, 100);
    auto sol = opti.solve();  // IPOPT under the hood
}

Contributing

Language and style: C++20, header-only, heavily templated. Formatting is enforced by nix fmt (clang-format). Run ./scripts/install-hooks.sh to auto-format on commit.

Adding tests: Test files live in tests/ and mirror the include/metis/ directory layout (tests/core/, tests/math/, tests/optimization/). Use GoogleTest. Run ./scripts/test.sh to verify.

Adding examples: Drop a .cpp file in the appropriate examples/ subdirectory and add it to examples/CMakeLists.txt. Run ./scripts/run_examples.sh to verify.

PR workflow: Fork, branch, make changes, ensure ./scripts/verify.sh passes (build + test + examples), open a PR against main.

Inspiration & Credits

Metis is heavily inspired by AeroSandbox, Peter Sharpe's Python-based design optimization framework. Metis serves as a C++ implementation and extension of the "Code Transformations" paradigm pioneered by Sharpe.

  • Primary Inspiration: AeroSandbox by Peter Sharpe.
  • Theoretical Foundation: Sharpe, Peter D. AeroSandbox: A Differentiable Framework for Aircraft Design Optimization. PhD Thesis, MIT, 2024. Read Thesis

Metis is built upon the shoulders of giants:

  • Eigen: For high-performance linear algebra and numeric storage.
  • CasADi: For symbolic graph generation, automatic differentiation, and optimization interfaces.

About

A Traceable Numerical Framework for Engineering Optimization

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages