Skip to content

Docs calibration howto#296

Open
thorek1 wants to merge 732 commits into
mainfrom
docs-calibration-howto
Open

Docs calibration howto#296
thorek1 wants to merge 732 commits into
mainfrom
docs-calibration-howto

Conversation

@thorek1

@thorek1 thorek1 commented May 13, 2026

Copy link
Copy Markdown
Owner

No description provided.

thorek1 and others added 30 commits April 23, 2026 06:30
… and skip comparisons for higher-order IRFs and variance when applicable
… distinct constants and enhance benchmark reporting for first-order solves

Co-authored-by: Copilot <copilot@github.com>
…alculations and update related comments

Co-authored-by: Copilot <copilot@github.com>
* Add Schur deflation for unit-root covariance computation

Models with unit-root eigenvalues (e.g., FRBUS with 23 unit roots) now compute
partial covariance matrices via Schur deflation. The approach:

1. When all standard Lyapunov solvers fail, decompose A = U*T*U' via real Schur
   factorization and reorder so unstable eigenvalues (|λ| ≥ 1 - 1e-8) come first.
2. Solve the Lyapunov equation only for the stable (lower-right) sub-block.
3. Map back to original coordinates; variables with any loading on unstable Schur
   vectors get NaN (infinite unconditional variance).

Changes:
- lyapunov.jl: Add solve_lyapunov_schur_deflation() and fallback in dispatch
- get_functions.jl: Optimize get_variance_decomposition with pre-computed Schur
  for per-shock solves; soften @Assert to @warn for covariance failures

Verified with FRBUS (89 stationary vars, 339 NaN), RBC, SW07, Guerrieri_Iacoviello.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Replace LinearAlgebra.schur/ordschur with FastLapackInterface.gees! in Schur deflation

Use FastLapackInterface.SchurWs and LAPACK.gees! with eigenvalue selection
(FastLapackInterface.ed) to perform Schur decomposition and eigenvalue
reordering in a single LAPACK call, replacing the separate schur() + ordschur()
sequence (lyapunov.jl) and eigvals() + schur() + ordschur() sequence
(get_functions.jl).

  gees! union return type behind concrete type assertions
- Use FastLapackInterface.ed with criterium=(1-tol)^2 to select unstable
  eigenvalues (exterior of disk) into the top-left Schur block
- Read n_unstable from workspace sdim field instead of counting eigenvalues

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Thread SchurWs workspace through lyapunov_workspace struct

Add FastLapackInterface.SchurWs{T} field to lyapunov_workspace, initialized
in the lyapunov_workspace struct instead.

- Add schur_ws field to lyapunov_workspace struct (structures.jl)
- Initialize with SchurWs(zeros(T,1,1)) in Lyapunov_workspace() constructor
  and get_variance_decomposition
- Move ensure_lyapunov_workspace! call before Schur decomposition in
  get_variance_decomposition so the workspace is available for both paths

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add early unit-root detection and fast Lyapunov dispatch

Detect unit roots from QME solution eigenvalues during first-order solve,
before any covariance computation. This avoids 3 wasted O(n³) Lyapunov
solver attempts for models with unit roots (e.g. FRBUS).

Changes:
- Add has_unit_roots::Bool field to caches struct with proper reset
- Detect unit roots from QZ eigenvalues in Schur QME path
- Detect unit roots from eigvals(sol) in doubling QME path (solution.jl)
- Add fast-path in Lyapunov dispatcher: skip directly to Schur deflation
- Thread has_unit_roots flag through moments.jl, get_functions.jl, rrules.jl
- Safety net: NaN detection in calculate_covariance as final fallback
- Skip unnecessary Schur in variance decomposition for non-unit-root models

Verified: RBC (no unit roots, all finite), FRBUS (89 finite, 339 NaN,
flag set during first-order solve before covariance call).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Rename _detect_unit_roots, _ordered_schur! to drop leading underscore

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Thore Kockerols <Thore.Kockerols@ecb.europa.eu>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nd update related function signatures

Co-authored-by: Copilot <copilot@github.com>
… job parameter in LAPACK call; only one pair of schur vectors
…m selector based on problem size; update relevant function signatures for consistency.

Co-authored-by: Copilot <copilot@github.com>
…ity for unit-root blocks

Co-authored-by: Copilot <copilot@github.com>
…oved accuracy. less tringent -> 1-e7; should allow NAWM to converge using schur
…nchmark-only mode

- Updated `extract_dynare_results.m` to include a benchmark-only mode for selective result extraction.
- Modified `generate_julia_results.jl` to support benchmark-only models and improved argument parsing for thread configuration.
- Enhanced `run_all_dynare.sh` to enforce single-thread execution in CI and added environment variable configurations for thread limits.
- Introduced `run_all_dynare_windows.ps1` for Windows environments, implementing similar functionality as the shell script with support for thread counts and model skipping.
- Added `run_thread_sweep_windows.ps1` to facilitate sweeping through different thread counts for performance benchmarking across models.

Co-authored-by: Copilot <copilot@github.com>
…tation

Co-authored-by: Copilot <copilot@github.com>
Thore Kockerols and others added 17 commits May 10, 2026 21:57
Add early return with NoTangent() in solve_sylvester_equation and
solve_lyapunov_equation pullbacks when the adjoint solve fails.
Previously the pullback continued computing gradients from the
failed solve result, producing garbage ∂A, ∂B, ∂C values.

Check Lyapunov solved flag in the Kalman filter rrule forward pass
and return on_failure_loglikelihood when it fails, instead of
silently proceeding with an invalid initial covariance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rebuild the neutral NSSS solver cache seed when clearing solution caches so long workflows cannot retain stale evicted warm-start entries.

Add regression coverage for final-horizon IRF parameter derivatives after forced NSSS solver-cache eviction.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The 'Gali :first_order (square obs)' test failed because the chosen
observables [:log_y, :log_W_real, :log_N] are linearly dependent in the
first-order solution. The model has the static identity W_real = Y^σ·N^φ
(from W_real = C^σ·N^φ and C = Y), which means the 3×3 shock Jacobian
is rank 2 and the LU factorization correctly fails.

Replace log_W_real with i_ann (annualized nominal interest rate), which
is determined by the Taylor rule and provides an independent channel for
the monetary policy shock.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add Mooncake NUTS sampling (100 samples) alongside existing ForwardDiff
- Add Mooncake vs ForwardDiff gradient comparison for combined objective
- Add Mooncake vs ForwardDiff gradient comparison for full log posterior
- Import Mooncake, DifferentiationInterface, AutoMooncake

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace min(norm(A*X²), norm(C)) normalization with the standard relative
residual from numerical linear algebra:

  norm(A*X² + B*X + C) / (norm(A*X²) + norm(B*X) + norm(C))

The previous min-based normalization (introduced in a765b3e) picked the
smallest of only two of three terms, making it degenerate when matrix term
scales differ by orders of magnitude — common in OBC models with many
auxiliary lag equations where norm(C) << norm(A*X²). The sum-of-terms
denominator is robust to arbitrary scale differences and accounts for all
three equation terms.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tests SS, first-order solution, and IRFs for a model with max()
operator (occasionally binding constraint), which exercises the
QME solver with large scale differences between matrix terms.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Changes in src/get_functions.jl:
  get_estimated_shocks, get_estimated_variables, get_model_estimates,
  get_estimated_variable_standard_deviations, get_loglikelihood) for
  reproducible outputs
- Fix get_statistics code: replace broken RBC.var with get_variables(RBC)
  and remove crashing parameters=get_parameters(RBC) kwarg
- Update get_conditional_forecast: shock names now include ₍ₓ₎ subscript
  (delta_eps₍ₓ₎, eps_z₍ₓ₎), column display updated for 80-char width
- Update get_solution: fix -0.0 to 0.0 in k₍₋₁₎ row
- Update get_solution(RBC, parameter_values): floating point values updated
- Update get_conditional_variance_decomposition: near-zero (:A) values
  (5.88e-32, 9.65e-31) now display as 0.0
- Update get_variance_decomposition: near-zero (:A) value (9.78e-31)
  now displays as 0.0
- Update get_statistics covariance output: truncated with … for 80-char width

Changes in src/inspect.jl:
- Update get_steady_state_equations: negation now parenthesized,
  :(-z{TFP} * ...) becomes :(-(z{TFP}) * ...)
- Update get_nonnegativity_auxiliary_variables: now returns 3 elements
  (➕₁, ➕₂, ➕₃) instead of 2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…blocks

- Add silent=true to all @parameters calls in jldoctest blocks to suppress
  non-deterministic timing output and model summary from being captured
- Add report_missing_parameters=false to doctests with intentionally
  incomplete parameter definitions (get_missing_parameters, has_missing_parameters)
- Fix get_conditional_forecast doctest: move alternative input format
  examples out of # output section into separate julia code block
- Fix get_statistics doctest: split multiple # output sections into
  tested jldoctest + illustrative julia blocks
- Fix get_non_stochastic_steady_state_residuals doctest: split multiple
  # output sections; add filter for machine-epsilon residual instability
- All 39 doctests now pass with doctest(MacroModelling)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 13, 2026 21:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@thorek1 thorek1 changed the base branch from main to optim_LFI_alloc May 13, 2026 21:18

## When to use calibration equations

Calibration equations are useful when an empirical target is easier to observe than the structural parameter itself. Common cases include:

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are usefeul for example when...
or simply when you want to pin down a steady state value

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are usefeul for example when...
or simply when you want to pin down a steady state value

K[ss] = K_ss | beta
```

### Multiple calibration equations in one block

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont see the added value of this

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont see the added value of this


## Common pitfalls

**No solution exists.** If the target is inconsistent with the model structure the steady-state solver will fail. For example, requesting a capital-output ratio that implies a negative depreciation rate has no valid solution. Review the target value and the model equations when this happens.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pick another example. this one is presented as trivial but is actually not.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pick another example. this one is presented as trivial but is actually not.


**No solution exists.** If the target is inconsistent with the model structure the steady-state solver will fail. For example, requesting a capital-output ratio that implies a negative depreciation rate has no valid solution. Review the target value and the model equations when this happens.

**Solver convergence.** The nonlinear solver needs a reasonable starting region. Providing bounds and initial guesses for calibrated parameters can help:

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

say that in the absolute majority of cases there is no need to provide a guess because the ss solver will most likely find the ss regardless but if the ss solver fails a guess can still be provided and will be helpful nonetheless. reformulate this in a more elegant way

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for bounds

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

say that in the absolute majority of cases there is no need to provide a guess because the ss solver will most likely find the ss regardless but if the ss solver fails a guess can still be provided and will be helpful nonetheless. reformulate this in a more elegant way. same for bounds


Bounds must be written as standalone comparison statements (e.g. `0 < α < 1` or `α > 0` on separate lines), not appended to the calibration equation. The `guess` keyword provides an initial value for the solver.

**One equation per parameter.** Each calibration equation pins exactly one parameter. Adding a second calibration equation for the same parameter, or using one equation for two parameters, will cause an error.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you cant use one equation for two parameters but you can use one equation twice for two parameters and that wont work. reformulate accordingly

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you cant use one equation for two parameters but you can use one equation twice for two parameters and that wont work. reformulate accordingly

get_steady_state(model_name)
```

The output table shows all steady-state variable values and calibrated parameter values. Check that the targeted variables match the specified values.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to check. the solver will say it failed, otherwise the calibration equations will be satisfied

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to check. the solver will say it failed, otherwise the calibration equations will be satisfied

@thorek1 thorek1 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot adress the comments


## When to use calibration equations

Calibration equations are useful when an empirical target is easier to observe than the structural parameter itself. Common cases include:

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are usefeul for example when...
or simply when you want to pin down a steady state value

K[ss] = K_ss | beta
```

### Multiple calibration equations in one block

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont see the added value of this


## Common pitfalls

**No solution exists.** If the target is inconsistent with the model structure the steady-state solver will fail. For example, requesting a capital-output ratio that implies a negative depreciation rate has no valid solution. Review the target value and the model equations when this happens.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pick another example. this one is presented as trivial but is actually not.


**No solution exists.** If the target is inconsistent with the model structure the steady-state solver will fail. For example, requesting a capital-output ratio that implies a negative depreciation rate has no valid solution. Review the target value and the model equations when this happens.

**Solver convergence.** The nonlinear solver needs a reasonable starting region. Providing bounds and initial guesses for calibrated parameters can help:

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

say that in the absolute majority of cases there is no need to provide a guess because the ss solver will most likely find the ss regardless but if the ss solver fails a guess can still be provided and will be helpful nonetheless. reformulate this in a more elegant way. same for bounds


Bounds must be written as standalone comparison statements (e.g. `0 < α < 1` or `α > 0` on separate lines), not appended to the calibration equation. The `guess` keyword provides an initial value for the solver.

**One equation per parameter.** Each calibration equation pins exactly one parameter. Adding a second calibration equation for the same parameter, or using one equation for two parameters, will cause an error.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you cant use one equation for two parameters but you can use one equation twice for two parameters and that wont work. reformulate accordingly

get_steady_state(model_name)
```

The output table shows all steady-state variable values and calibrated parameter values. Check that the targeted variables match the specified values.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to check. the solver will say it failed, otherwise the calibration equations will be satisfied

@codecov-commenter

codecov-commenter commented May 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.13004% with 408 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.92%. Comparing base (7a04ccb) to head (20aa134).
⚠️ Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
src/algorithms/lyapunov.jl 49.70% 85 Missing ⚠️
src/algorithms/sylvester.jl 58.76% 80 Missing ⚠️
src/parser/equation_modification.jl 75.60% 70 Missing ⚠️
src/parser/macros.jl 79.08% 55 Missing ⚠️
ext/ForwardDiffExt.jl 81.59% 30 Missing ⚠️
src/algorithms/fast_lapack_wrappers.jl 56.60% 23 Missing ⚠️
src/filter/inversion.jl 87.33% 19 Missing ⚠️
src/options_and_caches.jl 88.97% 15 Missing ⚠️
src/impulse_response_function.jl 76.47% 8 Missing ⚠️
src/filter/find_shocks.jl 85.00% 6 Missing ⚠️
... and 6 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #296      +/-   ##
==========================================
- Coverage   87.05%   86.92%   -0.13%     
==========================================
  Files          23       35      +12     
  Lines       14260    22603    +8343     
==========================================
+ Hits        12414    19648    +7234     
- Misses       1846     2955    +1109     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Base automatically changed from optim_LFI_alloc to main June 4, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants