Global Health Policy Simulation model
| Home | Quick Start | User Guide | Schemas | Models | Architecture | Data Model | Developer Guide | Technical docs | API |
Period: September 2025 - February 2026 Last updated: 20 February 2026
Related documentation: FINCH linear models guide · Income quintile factor means plan · Individual ID tracking plan · Same person ID plan · Architecture guide · Technical index
This report documents the integrated Health-GPS codebase changes delivered between November 2025 and February 2026. The work unifies support for India, ADB, and FINCH within a single branch, extends demographic and socioeconomic modelling, refines static and dynamic risk-factor pipelines, and adds analysis, disease, policy, and configuration capabilities described below.
The report is intended for modellers, economists, and developers who need a single reference for what changed, how modules interact, and where to look in the source tree. It complements the existing architecture guide, user guide, and quick start rather than replacing them.
The updates described in this report extend Health-GPS from a project-specific codebase into an integrated platform that supports multiple country and study configurations through shared modules, schemas, and input conventions.
Scope includes:
Behaviour is documented relative to the main branch as of 20 February 2026.
| Project | Status |
|---|---|
| India | Supported on the integrated branch |
| ADB | Supported on the integrated branch |
| FINCH | Supported on the integrated branch |
Backward compatibility: Legacy India configuration formats continue to work. Configurations may be migrated to the new format incrementally; the code accepts both old and revised schemas where stated in Section 12.
Repository note: When uploading JSON to healthgps-examples, existing Kevin Hall folders should be preserved. New JSON files should be added in a separate folder rather than replacing or deleting legacy examples.
The diagrams below describe the overall Health-GPS execution path - from program entry through simulation and output - rather than the per-person initialization sequence (see Section 14).
flowchart LR
DEMO[Demographic Module] --> SES[Socioeconomic Module]
SES --> RF[Risk Factor Module]
RF --> DIS[Disease Module]
DIS --> IO[Read/write to files]
Entry point: program.cpp. Run loop: runner.cpp. Population lifecycle: simulation.cpp (initialise_population, update_population).
flowchart TB
subgraph host [Host Application]
MAIN["main (program.cpp)"]
CLI[Parse CLI options]
CFG[Load config JSON]
DATA[Load datatable / DataManager]
REPO[Repository + register risk factor definitions]
FACTORY[Module factory]
MODEL_INPUT[Create ModelInput]
BUS[Create EventBus]
WRITERS[Result + optional ID-tracking writers]
MONITOR[EventMonitor]
RUNNER[Runner]
CHAN[SyncChannel]
CREATE_BASE[Create baseline Simulation]
CREATE_POL[Create intervention Simulation if configured]
RUN[Runner.run: baseline and optionally intervention]
STOP[EventMonitor.stop]
EXIT[Exit]
MAIN --> CLI --> CFG --> DATA --> REPO --> FACTORY
FACTORY --> MODEL_INPUT
MODEL_INPUT --> BUS --> WRITERS --> MONITOR
MONITOR --> RUNNER --> CHAN --> CREATE_BASE --> CREATE_POL --> RUN --> STOP --> EXIT
end
subgraph runLoop [Per-trial run loop]
SETUP[Setup run: seed]
SIM_ADD[Add Simulation to ADEVS Simulator]
INIT[Simulation.init: initialise_population]
TICK[Simulation.update: update_population]
FINI[Simulation.fini: cleanup]
SETUP --> SIM_ADD --> INIT --> TICK
TICK --> TICK
TICK --> FINI
end
subgraph initPop [initialise_population order]
D_INIT[Demographic]
SES_INIT[SES]
RF_INIT[Risk factor: static then dynamic]
DIS_INIT[Disease]
A_INIT[Analysis]
STATS[Print initial population statistics]
D_INIT --> SES_INIT --> RF_INIT --> DIS_INIT --> A_INIT --> STATS
end
subgraph updatePop [update_population order]
D_UPD[Demographic update]
MIG[Net immigration]
SES_UPD[SES update]
RF_UPD[Risk factor update]
DIS_UPD[Disease update]
A_UPD[Analysis update: publish results]
D_UPD --> MIG --> SES_UPD --> RF_UPD --> DIS_UPD --> A_UPD
end
subgraph output [Output]
PUB[Analysis publishes ResultEventMessage and optionally IndividualTrackingEventMessage]
DISPATCH[EventMonitor dispatch threads]
JSON_CSV[ResultFileWriter: JSON + main CSV + income CSVs]
TRACK[IndividualIDTrackingWriter: tracking CSV]
PUB --> DISPATCH --> JSON_CSV
PUB --> DISPATCH --> TRACK
end
RUN --> runLoop
INIT --> initPop
TICK --> updatePop
A_UPD --> PUB
| Area | Entry / main files |
|---|---|
| Program entry, config, data load | program.cpp |
| Run loop, trials, ADEVS | runner.cpp |
| Simulation init/update, module order | simulation.cpp |
| Demographic (age, gender, region, ethnicity) | demographic.cpp |
| SES (income) | SES module via factory (see demographic.cpp and config) |
| Risk factors (static, dynamic e.g. Kevin Hall) | static_linear_model.cpp, kevin_hall_model.cpp, riskfactor.cpp |
| Disease, PIF | default_disease_model.cpp, disease host module |
| Analysis, results aggregation | analysis_module.cpp |
| Result and ID-tracking output | result_file_writer.cpp, individual_id_tracking_writer.cpp, event_monitor.cpp |
| Config and schema | configuration.cpp, configuration_parsing.cpp, schema.cpp |
Health-GPS uses Intel TBB and core threading helpers in selected hot paths. The tables below summarise where concurrency is applied and where sequential execution is retained for correctness or reproducibility.
| Location | Mechanism | Rationale |
|---|---|---|
| Runner (runner.cpp) | Baseline and intervention run in parallel (two std::jthreads per trial when intervention is configured) |
Independent simulations; no shared mutable state between them |
| Program (program.cpp) | Async datatable load via core::run_async; TBB parallelism cap via -T |
Overlap I/O with startup; user-configurable thread count |
| Simulation (simulation.cpp) | tbb::parallel_for_each for population counts; core::run_async for expected population and input summary |
Per-person independence in aggregation |
| Demographic (demographic.cpp) | tbb::parallel_for_each for region/ethnicity assignment; async residual mortality |
Independent per-person assignment |
| Risk factor adjustable (risk_factor_adjustable_model.cpp) | tbb::parallel_for_each over population during adjustment |
Independent per-person adjustment |
| Disease (default_disease_model.cpp, default_cancer_model.cpp, disease.cpp) | tbb::parallel_for_each for incidence/remission; mutex on shared counters |
Parallel per-person updates; protected reduction |
| Analysis (analysis_module.cpp) | core::parallel_for over population; concurrent DALY and historical stats via core::run_async; sum_mutex on accumulators |
Large-population performance |
| Result writing (result_file_writer.cpp) | tbb::parallel_for_each over income categories; per-stream mutex |
Separate output files |
| Event bus (event_bus.cpp) | publish_async via core::run_async |
Non-blocking subscriber notification |
| EventMonitor (event_monitor.cpp) | Separate queues and dispatch threads for result vs individual-tracking messages | Parallel main-result and tracking writes (see parallelize output writes plan) |
| Location | Behaviour | Rationale |
|---|---|---|
| Static linear model (static_linear_model.cpp) | Sequential population loops | Shared model state; ordering and reproducibility |
| Kevin Hall model (kevin_hall_model.cpp) | Sequential per-person updates | Shared parameters; temporal dependencies |
| Simulation module order (simulation.cpp) | Strict Demographic → SES → Risk factor → Disease → Analysis | Cross-module data dependencies |
| Repository / model parser (repository.cpp, model_parser.cpp) | Single mutex on load/cache | Cache consistency |
| SyncChannel (baseline ↔ intervention) | Synchronous send/receive for net immigration etc. | Deterministic scenario coupling |
tbb::parallel_for_each, tbb::global_control::max_allowed_parallelism, tbb::concurrent_queue, tbb::task_group / task_group_contextcore::parallel_for, core::run_asyncFurther runtime notes: Performance optimizations.
| Feature | Description | Key code |
|---|---|---|
| Region | Assignment via region.csv by age and gender (random probability) |
demographic.cpp - initialise_region; repository.cpp - get_region_prevalence |
| Ethnicity | Assignment via ethnicity.csv by age and gender (random probability) |
initialise_ethnicity; get_ethnicity_prevalence |
| Gender | Encoding: 1 = Female, 0 = Male | Demographic module |
| Individual ID | Stable ID tracking across baseline and intervention runs | See individual ID tracking plan and same person ID plan |
income): Renamed to income_categorical; assignment via logits; category count is user-defined in config.income_continuous via linear regression on age, gender, region, ethnicity, and random noise; optional adjustment to factors mean; ranks values and assigns tertiles or quartiles per config.config.json / project_requirements.Reference: demographic.cpp, configuration.cpp, model_parser.cpp.
physical_activity replaced by simple_physical_activity (random probability, constant mean, small standard deviation).income_continuous, and noise; optional factors-mean adjustment.logistic_regression.csv.Reference: static_linear_model.cpp, risk_factor_adjustable_model.cpp. Modeller-facing detail: FINCH linear models guide.
get_expected: Physical activity is read from factors-mean CSV data rather than hardcoded values when setting expected weight.Reference: kevin_hall_model.cpp.
income_category with corrected assignment logic.is_active() calls in analysis hot paths - see parallelize output writes plan.Reference: analysis_module.cpp, result_file_writer.cpp, individual_id_tracking_writer.cpp.
incidence × (1 - PIF), with PIF depending on age, gender, years post intervention, and disease-specific values. Configurable on/off.Reference: default_disease_model.cpp, pif_data.cpp.
Policy implementation may start from a user-specified year. For the ADB paper, implementation begins in the first simulation year. The code default is the second year; config overrides this behaviour.
Reference: configuration.cpp, configuration_parsing.cpp.
Config extensions:
income_categoricalnull, UPF_trend, income_trendproject_requirements (demographics, income layout, PA, trends, two-stage flags - see project requirements plan)Static model: User-specified file names and columns for region, ethnicity, income, physical activity, logistic regression, Box-Cox, and policy models.
Dynamic model: Kevin Hall parameters in dynamic model JSON.
Schemas: Act as intermediaries to CSV inputs in Health-GPS-examples (file-name placeholders rather than full coefficient listings). Legacy configs remain valid; extended schema options include income categories (3 or 4), trend type, income-based output, adjust-to-factors-mean, trended adjustment, and policy start year.
Reference: configuration.cpp, configuration_parsing.cpp, schema.cpp.
The names_ vector in the model parser preserves a consistent order for risk-factor correlation and covariance data. It contains risk-factor names (e.g. carbohydrate, sugar, protein) and excludes weight, height, BMI, income, physical activity, and energy intake - quantities supplied via dynamic model JSON and used in kevin_hall_model.cpp.
Reference: model_parser.cpp.
Per-person initialization follows this order:
Age, Gender, Region (if configured), Ethnicity (if configured), Sector (if configured), Income [Categorical: direct assignment (e.g. India) or Continuous: compute value, rank, assign categories (e.g. FINCH)], Risk factors [Two-stage: logistic then Box-Cox or Box-Cox only], Physical activity [Simple PA or continuous PA regression], Adjust to factors mean (if enabled), Policies (if enabled), Trends (if enabled), Trended risk-factor adjustment and Disease model.
flowchart TB
A[Age] --> B[Gender]
B --> C["Region (if configured)"]
C --> D["Ethnicity (if configured)"]
D --> E["Sector (if configured)"]
E --> F[Income]
F --> G["Categorical assignment<br/>(e.g. India)"]
F --> H["Continuous value + categories<br/>(e.g. FINCH)"]
G --> I[Risk factors]
H --> I
I --> I1["Two-stage path<br/>logistic then Box-Cox"]
I --> I2["Single-stage path<br/>Box-Cox only"]
I1 --> RFA[Risk factors assigned]
I2 --> RFA
RFA --> J[Physical activity]
J --> J1[Simple PA]
J --> J2[Continuous PA]
J1 --> PAD[PA assigned]
J2 --> PAD
PAD --> K["Factors-mean adjustment<br/>(if enabled)"]
K --> L["Policies<br/>(if enabled)"]
L --> M["Trends<br/>(if enabled)"]
M --> N["UPF trend"]
M --> O["Income trend"]
N --> P[Trended RF adjustment]
O --> P
P --> Q[Disease model]
The integrated codebase supports India, ADB, and FINCH. The following items from the original work plan are complete:
| Item | Description |
|---|---|
| Food section | Remove from config/schema where applicable |
| DataFile.csv | Remove from config |
| SES model | Remove from config |
| Level property | Remove from schemas |
Whether income and physical activity are adjusted to factors mean for India as well as FINCH should be confirmed against project configs and reference runs. Behaviour is config-driven; defaults may differ by project.
The following test files were updated or added to cover the integrated behaviour:
| Test file | Coverage area |
|---|---|
| Population.Test.cpp | Person ID assignment |
| ConfigSchemaExpanded.Test.cpp | Extended config/schema |
| RepositoryPIF.Test.cpp | PIF data loading |
| PIFIntegration.Test.cpp | PIF integration |
| PIFData.Test.cpp | PIF data structures |
| DiseaseModelPIF.Test.cpp | Disease + PIF |
| DataManagerPIF.Test.cpp | Data manager PIF |
| ConfigurationPIF.Test.cpp | Config PIF options |
| Simulation.Test.cpp | Simulation integration (where touched) |
| PredictorResolver.Test.cpp | Predictor naming and gender2 |
| IncomeStratumAdjustment.Test.cpp | Income-stratum factors-mean adjustment |
Example runs and configuration: quick start.
| Document | Purpose |
|---|---|
| FINCH linear models guide | Policy equations, predictors, income-stratum adjustment |
| Performance optimizations | Parallel trial execution and runtime tuning |
| Individual ID tracking plan | Per-person CSV output design |
| Same person ID plan | ID assignment across scenarios |
| Income quintile factor means plan | Optional stratum-specific adjustment |
| Architecture guide | Core system design |
| Developer Guide | Build, CMake, vcpkg |
| MSVC troubleshooting | Windows toolset / Ninja environment failures |
| Technical index | Full technical documentation listing |
| User Guide | Configuration and HPC usage |
| Documentation index | Documentation map |
February 2026 - integrated Health-GPS codebase (India, ADB, FINCH).
Author: Mahima Ghosh