Implementing a new correlation model in hazardlib#
Ground-motion correlation models describe dependence between residuals at different sites, between different intensity measure types (IMTs), or both. They are used when generating ground-motion fields, conditioning fields on observations, and computing products such as conditional spectra.
Before contributing a model, read the development guidelines and the testing guide. The scientific terminology used below is introduced in the ground-motion correlation page.
Establish the scientific specification#
Establish the model’s scientific specification from authoritative sources, such as the original publication and supplements, published corrections, or software maintained by the authors. If sources disagree, explain which interpretation is followed and why.
Before implementation, identify:
the residual component for which the model was calibrated:
WITHIN_EVENT,BETWEEN_EVENT, orTOTALwhether it describes spatial, cross-IMT, or joint spatial-cross-IMT correlation
the supported IMTs, spectral-period range, damping, and intensity measure component definition
the definition and units of separation distance
regional, magnitude, site or rupture restrictions
required model parameters and rupture context
interpolation, extrapolation and boundary rules
whether the resulting matrices are expected to be positive semidefinite
Reflect the applicable details in the model metadata, validation, tests, and pull request description.
Select the model interface#
The base interfaces are defined in
openquake/hazardlib/correlation_models/base.py.
Subclass
SpatialCorrelationModelwhen the model correlates one IMT across sites. Implement_correlation_matrix.Subclass
CrossIMTCorrelationModelwhen the model correlates different IMTs at one site. Implement_rho.Subclass
SpatialCrossIMTCorrelationModelwhen the model directly describes a joint field across sites and IMTs. Implement_correlation_block.
A joint model should implement _correlation_block rather than only
covariance. Conditioning requires rectangular covariance blocks between two
different collections of sites and IMTs. The returned rows and columns must be
in IMT-major order: all sites for the first IMT, followed by all sites for the
second IMT, and so on. The public methods perform shared validation before
calling these protected numerical methods.
Place the implementation in the matching package:
openquake/hazardlib/correlation_models/
spatial/
cross_imt/
spatial_cross_imt/
Use a lowercase file name and a CamelCase class name containing the authors’
names and publication year. For example, loth_baker_2013.py contains
LothBaker2013. Each model should be implemented in its own dedicated file.
Declare model metadata#
Every scientific model must declare its residual component and the IMTs accepted by its implementation:
from openquake.hazardlib.imt import PGA
DEFINED_FOR_RESIDUAL_COMPONENT = ResidualComponent.WITHIN_EVENT
DEFINED_FOR_INTENSITY_MEASURE_TYPES = {PGA}
Mandatory metadata#
DEFINED_FOR_RESIDUAL_COMPONENTisWITHIN_EVENT,BETWEEN_EVENT, orTOTAL.DEFINED_FOR_INTENSITY_MEASURE_TYPESlists the IMT classes accepted by the implementation, following the existing GSIM convention. Clearly distinguish accepted operational approximations from calibrated IMTs.
Conditional metadata#
Declare the following metadata only when it applies:
DEFINED_FOR_INTENSITY_MEASURE_COMPONENTidentifies a component established by the publication, using a member ofopenquake.hazardlib.const.IMC.CALIBRATED_FOR_INTENSITY_MEASURE_TYPESlists the IMTs used to derive the model when they differ from the accepted IMTs. Omit it when it matches the accepted IMT set.INTENSITY_MEASURE_TYPE_APPROXIMATIONSmaps each accepted IMT factory to the IMT that represents it when an operational proxy is explicitly supported.DEFINED_FOR_SA_DAMPINGgives the supported spectral damping, when applicable.DEFINED_FOR_SA_PERIOD_RANGEgives the inclusive calibrated period range.DEFINED_FOR_REGIONrecords an explicit geographic applicability or calibration restriction. Most models should inherit the defaultNone.
For example, an SA model that also accepts PGA as a documented SA(0.01) proxy would declare the following applicable metadata:
from openquake.hazardlib import const
from openquake.hazardlib.imt import PGA, SA
DEFINED_FOR_INTENSITY_MEASURE_TYPES = {PGA, SA}
DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = const.IMC.RotD50
CALIBRATED_FOR_INTENSITY_MEASURE_TYPES = {SA}
INTENSITY_MEASURE_TYPE_APPROXIMATIONS = {PGA: SA(0.01)}
DEFINED_FOR_SA_DAMPING = 5.0
DEFINED_FOR_SA_PERIOD_RANGE = (0.01, 5.0)
Use None only when a field genuinely does not apply or the model is not
restricted; concrete classes do not need to repeat optional metadata with a
None value. The base classes validate IMT names, spectral periods, damping,
residual components, distance matrices and returned matrix values. Do not infer
a proxy SA period for an unsupported IMT merely from a similar period. A proxy
established by an authoritative source or operational convention must be
scientifically justified, explicitly documented and tested. Implement only
validation specific to an IMT combination, component definition or constructor
parameter in the concrete class.
Register the model#
Decorate the class with register_model:
@register_model(
description='Example within-event joint correlation')
class ExampleModel2026(SpatialCrossIMTCorrelationModel):
...
The class name is the canonical configuration name. Use aliases only for established alternative names or backward compatibility.
The registry discovers model modules lazily. Do not import them from package
__init__.py files.
Constructor arguments become the values accepted by the corresponding
*_correlation_params job parameter. Constructors should retain only validated
configuration and inexpensive reusable data. If loading or interpolation setup
is expensive, perform it once at construction and make sure the object remains
serializable.
Implement the numerical model#
Correlation methods return dimensionless correlation coefficients. Calculators
scale normalized correlated residuals with the standard deviation of the
modelled component: GSIM-provided phi for within-event, tau for
between-event, or sigma for total residuals.
Implementations should:
use kilometres for site separation
accept NumPy arrays and vectorize over site pairs where practical
preserve symmetry under exchange of sites and IMTs
return a unit diagonal when required by the model
avoid modifying input arrays
retain coefficient precision supplied by the model authors
Return the correlation defined by the model without silently repairing it. Generic positive-semidefinite repair, when needed for sampling, belongs in the common factorization machinery.
Add independent verification tests#
Reference values should be produced independently of the hazardlib implementation. Use values or tables preferably published by the authors or author-maintained software, or otherwise generated by an independent implementation. Store only small immutable verification tables in the repository as conventional data files without embedded provenance comments. Record their source and version, input grid, and tolerances in the pull request description.
Use both relative and absolute tolerances because valid correlations can be zero or close to zero. A model test should cover:
tabulated nodes and interior interpolation points
period and distance boundaries
invalid IMTs, periods, damping and parameters
symmetry and the diagonal
representative bounds and positive-semidefinite matrices
IMT-major matrix ordering
rectangular blocks for direct joint models
factor reconstruction
Use deterministic matrix tests rather than large Monte Carlo tests. Sampling statistics are tested by the common factorization tests and need not be implemented at the individual model level.
Shared interface and registry tests belong in
openquake/hazardlib/tests/correlation_models_test.py.
Put new model-specific material under:
openquake/hazardlib/tests/correlation_models/
<model_name>_test.py
data/<MODEL_NAME>/
Keep each model’s numerical tests and reference data in its own test module and data directory.
During development, run the model test and correlation tests frequently
locally. Then run hazardlib, the relevant calculator tests, ruff, and finally
the complete oq-engine test suite before opening the pull request. See the
testing guide for the standard commands.
Document and submit the model#
The model module must list the complete bibliographic reference and its DOI, when one exists. Also:
add its module to the correlation-model API reference
update the scientific page if the model introduces a new model family, residual component or limitation
update
debian/changelogkeep the implementation, reference data and tests in the same pull request
The pull request should explain the calibration domain, reference-data provenance, maximum discrepancies, and any choices made where publications or external implementations disagree.