Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ ogcore/tests/OUTPUT_REFORM/*
regression/OUTPUT_BASELINE/*
regression/OUTPUT_REFORM*
.vscode/
.claude/
*default.profraw
*un_api_token.txt
129 changes: 25 additions & 104 deletions CHANGELOG.md

Large diffs are not rendered by default.

59 changes: 27 additions & 32 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,75 +5,70 @@
# to work in that environment (and not on Windows).
# USAGE: OG-Core$ make [TARGET]

.PHONY=help
.PHONY: help
help:
@echo "USAGE: make [TARGET]"
@echo "TARGETS:"
@echo "help : show help message"
@echo "clean : remove .pyc files and local ogcore package"
@echo "install : build and install local package"
@echo "pytest : generate report for and cleanup after"
@echo " pytest -W ignore -m ''"
@echo "cstest : generate coding-style errors using the"
@echo " pycodestyle (nee pep8) tool"
@echo "pytest_all : run all tests"
@echo "pytest_ci : run same set of tests as GitHub Actions CI"
@echo "coverage : generate test coverage report"
@echo "git-sync : synchronize local, origin, and upstream Git repos"
@echo "git-pr N=n : create local pr-n branch containing upstream PR"
@echo "documentation : build new Jupyter Book documentation files"
@echo "format : format code using ruff and linecheck"

.PHONY=clean
.PHONY: clean
clean:
@find . -name *pyc -exec rm {} \;
@find . -name *cache -maxdepth 1 -exec rm -r {} \;
@conda uninstall ogcore --yes --quiet 2>&1 > /dev/null
@find . -name '*.pyc' -delete
@find . -maxdepth 1 -name '*cache' -exec rm -r {} +

.PHONY=install
.PHONY: install
install:
pip install -e .[dev]
uv sync --extra dev --extra docs

.PHONY=pytest
pytest:
@cd ogcore ; pytest -W ignore
.PHONY: pytest_all
pytest_all:
uv run python -m pytest

ogcore_JSON_FILES := $(shell ls -l ./ogcore/*json | awk '{print $$9}')
.PHONY: pytest_ci
pytest_ci:
uv run python -m pytest -m "not local and not benchmark"

.PHONY=cstest
cstest:
-pycodestyle ogcore
-pycodestyle --ignore=E501,E121 $(ogcore_JSON_FILES)
ogcore_JSON_FILES := $(shell ls -l ./ogcore/*json | awk '{print $$9}')

define coverage-cleanup
rm -f .coverage htmlcov/*
endef

COVMARK = ""
COVMARK = "not local and not benchmark"

OS := $(shell uname -s)

.PHONY=coverage
.PHONY: coverage
coverage:
@$(coverage-cleanup)
@coverage run -m pytest -v -m $(COVMARK) > /dev/null
@coverage html --ignore-errors
uv run python -m pytest -m $(COVMARK) -n 4 --cov=ogcore --cov-report=html --cov-report=term
ifeq ($(OS), Darwin) # on Mac OS X
@open htmlcov/index.html
else
@echo "Open htmlcov/index.html in browser to view report"
endif
@$(pytest-cleanup)

.PHONY=documentation
.PHONY: documentation
documentation:
uv run python -m ipykernel install --user --name=ogcore-dev
uv run jb clean docs
uv run python ./docs/make_params.py
uv run python ./docs/make_vars.py
uv run jb build ./docs/book
uv run --extra docs python -m ipykernel install --user --name=ogcore-dev
uv run --extra docs jb clean docs
uv run --extra docs python ./docs/make_params.py
uv run --extra docs python ./docs/make_vars.py
uv run --extra docs jb build ./docs/book

.PHONY: format
format:
uv run ruff format .
uv run ruff check . --fix
uv run linecheck . --fix

.PHONY: pip-package
pip-package:
uv build
2 changes: 2 additions & 0 deletions docs/book/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ sphinx:
extra_extensions : ['sphinx.ext.autodoc', 'sphinx.ext.mathjax',
'sphinx.ext.viewcode', 'sphinx.ext.napoleon',
'alabaster'] # A list of extra extensions to load by Sphinx.
local_extensions : # Local extensions, "name: path" (path relative to this file)
suppress_header_warnings : _ext
config : # key-value pairs to directly over-ride the Sphinx configuration
bibtex_reference_style: author_year
mathjax_path : https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
Expand Down
48 changes: 48 additions & 0 deletions docs/book/_ext/suppress_header_warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Suppress MyST ``myst.header`` warnings for the auto-generated pages.

``docs/book/content/intro/parameters.md`` and ``variables.md`` are written by
``docs/make_params.py`` and ``docs/make_vars.py``. Both deliberately place the
parameter/variable headings two levels below their section heading (H2 to H4),
which MyST reports as "Non-consecutive header level increase". MyST reads
Sphinx's global ``suppress_warnings`` setting, so silencing ``myst.header``
there would silence it for the whole book. This extension instead drops those
records only when they come from the two generated files.
"""

import logging
import os

TARGETS = (
"content/intro/parameters.md",
"content/intro/variables.md",
)
SUBTYPE = "[myst.header]"


class HeaderWarningFilter(logging.Filter):
"""Drop ``myst.header`` warnings raised by the generated pages."""

def filter(self, record):
if SUBTYPE not in str(record.msg):
return True
location = str(getattr(record, "location", "") or "")
location = location.replace(os.sep, "/")
return not any(target in location for target in TARGETS)


def _add_filter(app):
log_filter = HeaderWarningFilter()
for handler in logging.getLogger("sphinx").handlers:
# Insert ahead of Sphinx's own filters: WarningSuppressor increments
# the build's warning count and WarningIsErrorFilter raises under
# ``-W``, and both run before any filter added with addFilter().
handler.filters.insert(0, log_filter)


def setup(app):
app.connect("builder-inited", _add_filter)
return {
"version": "1.0",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
21 changes: 21 additions & 0 deletions docs/book/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ parts:
- caption: OG-Core API
chapters:
- file: content/api/public_api
sections:
- file: content/api/aggregates
- file: content/api/config
- file: content/api/demographics
- file: content/api/elliptical_u_est
- file: content/api/execute
- file: content/api/firm
- file: content/api/fiscal
- file: content/api/household
- file: content/api/output_plots
- file: content/api/output_tables
- file: content/api/parameter_plots
- file: content/api/parameter_tables
- file: content/api/parameters
- file: content/api/pensions
- file: content/api/solvers
- file: content/api/SS
- file: content/api/tax
- file: content/api/TPI
- file: content/api/txfunc
- file: content/api/utils
- caption: OG-Core Theory
chapters:
- file: content/theory/intro
Expand Down
13 changes: 13 additions & 0 deletions docs/book/content/api/SS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.. _SS:

Steady-State Functions
=================================================

**SS.py modules**

ogcore.SS
------------------------------------------

.. automodule:: ogcore.SS
:members: euler_equation_solver, solve_for_j, inner_loop, SS_solver,
SS_fsolve, SS_initial_guesses, run_SS
13 changes: 13 additions & 0 deletions docs/book/content/api/TPI.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.. _TPI:

Transition Path Functions
=================================================

**TPI.py modules**

ogcore.TPI
------------------------------------------

.. automodule:: ogcore.TPI
:members: get_initial_SS_values, firstdoughnutring, twist_doughnut,
inner_loop, run_TPI
12 changes: 12 additions & 0 deletions docs/book/content/api/config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.. _config:

Logging Configuration
=================================================

**config.py modules**

ogcore.config
------------------------------------------

.. automodule:: ogcore.config
:members: set_logging_level
24 changes: 1 addition & 23 deletions docs/book/content/api/public_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,4 @@ make up the `OG-Core` model. Below is a list of these modules (in alphabetical
order) with documentation about how to call each class method and function.
There is also a link to the source code for each documented member.

.. toctree::
:maxdepth: 1

aggregates
config
demographics
elliptical_u_est
execute
firm
fiscal
household
output_plots
output_tables
parameter_plots
parameter_tables
parameters
pensions
solvers
SS
tax
TPI
txfunc
utils
.. tableofcontents::
72 changes: 70 additions & 2 deletions docs/book/content/intro/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ _Out-of-Range Action:_ error
### Fiscal Policy Parameters

#### `alpha_FA`
_Description:_ Foreign aid payments to domestic government as a share of GDP.
_Description:_ Foreign aid payments to domestic government as a share of GDP. Set value for base year, click '+' to add value for next year. All future years not specified are set to last value entered.
_Value Type:_ float
_Valid Range:_ min = 0.0 and max = 1.0
_Out-of-Range Action:_ error
Expand Down Expand Up @@ -855,29 +855,97 @@ _Valid Range:_ min = -1.0 and max = 1.0
_Out-of-Range Action:_ error


#### `g_n_preTP`
_Description:_ Population growth rate from year before model start to start year.
_Value Type:_ float
_Valid Range:_ min = -1.0 and max = 1.0
_Out-of-Range Action:_ error


#### `imm_rates`
_Description:_ Immigration rates over the time path.
_Value Type:_ float
_Valid Range:_ min = -1.0 and max = 1.0
_Out-of-Range Action:_ error


#### `imm_rates_preTP`
_Description:_ Immigration rates in period before model start year.
_Value Type:_ float
_Valid Range:_ min = -1.0 and max = 1.0
_Out-of-Range Action:_ error


#### `rho`
_Description:_ Age-specific mortality rates.
_Value Type:_ float
_Valid Range:_ min = 0.0 and max = 1.0
_Out-of-Range Action:_ error


#### `rho_preTP`
_Description:_ Age-specific mortality rates.
_Value Type:_ float
_Valid Range:_ min = 0.0 and max = 1.0
_Out-of-Range Action:_ error


## Model Solution Parameters

#### `use_sparse_FOC_jac`
_Description:_ Flag to use a sparse (banded) finite-difference Jacobian in the household first order condition root finder. When True (the default), the sparsity pattern of the stacked Euler/labor first order conditions is auto-detected once per problem size and supplied to scipy.optimize.root, which then needs far fewer function evaluations per Jacobian build than the default dense finite differences. The solver falls back to the dense finite-difference Jacobian automatically if the Jacobian is not sparse enough to benefit or if a solve fails. Set to False to use the legacy dense Jacobian on every call.
_Value Type:_ bool
_Valid Choices:_[True, False]


#### `nu`
_Description:_ Parameter for convergence rate of functional iteration.
_Value Type:_ float
_Valid Range:_ min = 0.01 and max = 0.5
_Out-of-Range Action:_ error


#### `TPI_outer_method`
_Description:_ Update rule for the transition-path outer loop. 'picard' (default) is the model's historical damped functional iteration x <- (1-nu) x + nu G(x) (see nu), which leaves model solutions unchanged. 'anderson' uses limited-memory Anderson acceleration on the residual history to take larger, better-directed steps, guarded by a trust region anchored to the damped point (TPI_trust_radius).
_Notes:_ Opt-in solver acceleration. The default ('picard') reproduces the constant-nu behavior exactly.
_Value Type:_ str
_Valid Choices:_['picard', 'anderson']


#### `TPI_anderson_m`
_Description:_ Number of past iterate/residual differences retained by the Anderson accelerator when TPI_outer_method='anderson'. Ignored otherwise.
_Value Type:_ int
_Valid Range:_ min = 1 and max = 50
_Out-of-Range Action:_ error


#### `TPI_anderson_beta`
_Description:_ Mixing weight for the Anderson step when TPI_outer_method='anderson'. beta=1 is undamped; beta<1 adds damping for robustness far from the solution. Ignored otherwise.
_Value Type:_ float
_Valid Range:_ min = 0.1 and max = 1.0
_Out-of-Range Action:_ error


#### `TPI_trust_radius`
_Description:_ Initial trust radius for the accelerated TPI step, as a multiple of the damped functional-iteration step length around the always-feasible damped point. Grown after an improving iteration and shrunk (with a reset) after a worsening one. A non-positive value disables the trust region (unguarded accelerator; not recommended). Ignored when TPI_outer_method='picard'.
_Value Type:_ float
_Valid Range:_ min = 0.0 and max = 100.0
_Out-of-Range Action:_ error


#### `TPI_stall_window`
_Description:_ Number of trailing TPI outer-loop iterations over which the best distance must improve on the best from before the window. When it does not, the loop has stalled (cycling or diverging) and a diagnosis is logged; see TPI_stall_action for whether the loop also stops. A value of 0 disables stall detection.
_Value Type:_ int
_Valid Range:_ min = 0 and max = 500
_Out-of-Range Action:_ error


#### `TPI_stall_action`
_Description:_ What to do when stall detection (TPI_stall_window) diagnoses a stalled TPI outer loop. 'warn' (default) logs the diagnosis once and lets the loop continue, leaving model solutions unchanged; 'stop' also ends the loop early, so the run fails through the usual non-convergence checks instead of spending the rest of maxiter.
_Value Type:_ str
_Valid Choices:_['warn', 'stop']


#### `SS_root_method`
_Description:_ Root finding algorithm for outer loop of the SS solution.
_Notes:_ Uses scipy.optimize.root, please see scipy documentation for description of methods. Note that some methods may require more arguments than are in the function calls in SS.py and TPI.py and will therefore break without modifications of the source code.
Expand Down Expand Up @@ -960,7 +1028,7 @@ _Out-of-Range Action:_ error
_Description:_ Calendar year in which to start model analysis.
_Notes:_ Calendar year for initial model period
_Value Type:_ int
_Valid Range:_ min = 2013 and max = 2100
_Valid Range:_ min = 2013 and max = 2101
_Out-of-Range Action:_ error


Expand Down
2 changes: 1 addition & 1 deletion ogcore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
from ogcore.txfunc import * # noqa: F403
from ogcore.utils import * # noqa: F403

__version__ = "0.19.1"
__version__ = "0.19.2"
Loading
Loading