Known-matrix relatedness with relmat
Status — Stable (Gaussian mean, supplied K)
Mirrors drmTMB's Known-matrix relatedness with relmat. In DRM.jl today: relmat(1 | id) with a user-supplied relatedness matrix K on the Gaussian mean — a structured random intercept fit in closed form. animal() (pedigree) and phylo() (tree) reuse this engine.
When units are related by a known matrix — a pedigree, a phylogeny, a kinship matrix — the random intercept is no longer i.i.d.: u ~ N(0, σ_s² K) with K the known relatedness. For a Gaussian mean the marginal stays Gaussian, y ~ N(Xβ, D + σ_s² Z K Zᵀ), so DRM.jl fits it in closed form (PGLS-style, no approximation). Supply K (ordered by the grouping's first appearance):
using DRM, Random, LinearAlgebra
Random.seed!(1)
G = 40
A = let M = randn(G, G); M * M' / G + I end # build a relatedness matrix
d = sqrt.(diag(A)); K = A ./ (d * d') # → a correlation matrix
m = 5; n = G * m
id = repeat(1:G, inner = m)
x = randn(n)
u = 0.7 .* (cholesky(Symmetric(K)).L * randn(G)) # structured effect u ~ N(0, 0.7² K)
y = 0.3 .+ 0.5 .* x .+ u[id] .+ 0.4 .* randn(n)
fit = drm(bf(@formula(y ~ x + relmat(1 | id)), @formula(sigma ~ 1)),
Gaussian(); data = (; y, x, id), K = K)
re_sd(fit)[:id] # structured-effect SD (≈ 0.7)0.7359150303405382exp(coef(fit, :sigma)[1]) # residual SD (≈ 0.4)0.41149564584150644K must be ordered to match the levels of id as they first appear in the data. The same engine powers animal(1 | id) (with a pedigree-derived A) and phylo(1 | species) (with a tree-derived correlation).
Gaussian mean vs location-scale
This closed-form path is for structured effects on the mean. When the structured effect also acts on log σ (the q=4 phylogenetic location-scale model), DRM.jl uses its verified sparse-Laplace engine — see HANDOVER.md.