Skip to content

Add intrinsic three-component thin-disk AGN SED with strict energy-closure scaling#1069

Open
Copilot wants to merge 11 commits intomasterfrom
copilot/add-strict-energy-closure-scaling
Open

Add intrinsic three-component thin-disk AGN SED with strict energy-closure scaling#1069
Copilot wants to merge 11 commits intomasterfrom
copilot/add-strict-energy-closure-scaling

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 12, 2026

Adds accretionDiskSpectraThinDisk, a pure-Fortran accretion disk spectra class that computes a three-component AGN SED directly from BH properties (mass, spin, accretion rate), extending to hard X-rays (~300 keV). Unlike the existing hopkins2007 implementation, this requires no external code download or HDF5 table at runtime.

Components & energy closure

All three components share the bolometric luminosity exactly (f_disk + f_warm + f_hot = 1):

  • Disk — multitemperature blackbody with Novikov–Thorne profile T(x) = T_max x^{-3/4}(1 − x^{-1/2})^{1/4}. Peak temperature derived analytically from L_disk = 4π σ r_isco² T_max⁴ / 3; spectrum computed by radial quadrature over t = ln(r/r_isco).
  • Warm coronaν^{−Γ_warm} exp(−hν/E_warm), normalized via Γ(1−Γ, E_min/E_warm) (upper incomplete gamma) so ∫S dν = f_warm L_bol exactly.
  • Hot corona — same form with independent Γ_hot, E_hot; integral equals f_hot L_bol exactly.

Thin-disk gate & caching

  • Returns zero when ṁ/ṁ_Edd < mdotThinMinimum (default 0.01).
  • Full SED computed once per node and cached via node%uniqueID() + lastSEDComputed flag; cache cleared on calculationResetEvent.

Parameters (all have defaults)

Parameter Default Meaning
mdotThinMinimum 0.01 Eddington fraction threshold
fractionHot / fractionWarm 0.02 / 0.05 Bolometric fractions
temperatureHot / temperatureWarm 100 / 0.2 keV Exponential cutoff energies
spectralIndexHot / spectralIndexWarm 1.7 / 2.5 Power-law photon indices
energyMinimumHot / energyMinimumWarm 0.1 / 0.001 keV Low-energy cutoffs
massBlackHoleFiducial / spinBlackHoleFiducial 10⁸ M☉ / 0.5 Used by spectrumMassRate

Example parameter block:

<accretionDiskSpectra value="thinDisk">
  <fractionHot value="0.02"/>
  <fractionWarm value="0.05"/>
  <temperatureHot value="100.0"/>
  <spectralIndexHot value="1.7"/>
</accretionDiskSpectra>
Original prompt

Add strict energy-closure scaling to the new intrinsic thin-disk AGN SED implementation (disk + warm + hot corona), and open a PR.

Repo: galacticusorg/galacticus
Base branch: master

Context

  • There is an existing accretion disk spectra implementation based on Hopkins2007 (source/accretion_disks.spectra.Hopkins2007.F90) which builds an HDF5 table by downloading/compiling external code at runtime.
  • We are adding a new pure-Fortran intrinsic SED class that computes directly from BH properties (mass, spin, accretion rate) and extends to hard X-rays (up to 300 keV).
  • The new class should apply only in the thin-disk regime (e.g., Mdot/MdotEdd >= mdotThinMinimum).
  • Caching should be keyed by node%uniqueID().
  • The new class will be auto-discovered by the directive block:
  • The build system will pick up the new file automatically; no build system edits are required.

Task

  1. Implement (or update) the new Fortran module file:
    source/accretion_disks.spectra.disk_corona_intrinsic.F90
    defining an accretionDiskSpectra implementation named:
    accretionDiskSpectraDiskCoronaIntrinsic
    that returns intrinsic SED Lsun/Hz at wavelength (Angstrom).

  2. Add a strict energy-closure fix for the disk component:

    • Compute the disk spectral shape S_nu on the internal wavelength grid.
    • Compute its bolometric luminosity (integral over frequency: ∫ Lnu dnu).
    • Scale disk Lnu by a factor so that the bolometric integral equals Lout (the power assigned to disk outside Rcor).
    • Ensure Lin = Lbol - Lout is split into warm/hot components via fWarm and fHot, and that warm/hot normalizations integrate to their assigned luminosities.
  3. Keep the model pure Fortran (no runtime downloads/compiles) and include hard X-rays up to 300 keV (lambdaMinA ~ 12.3984193/300 Å).

  4. Preserve/implement caching using node%uniqueID() so per-node expensive normalizations are computed only when node changes.

  5. Add basic safeguards:

    • Handle cases where accretion rate is non-positive, or bolometric luminosity <= 0.
    • If mdot < mdotThinMinimum return 0.
    • Ensure fWarm and fHot are non-negative and renormalized to sum to 1 if necessary.
    • Prevent negative returned fluxes.
  6. Add/maintain input parameters in the directive block to make the main model parameters configurable:
    mdotThinMinimum, lambdaCount, lambdaMinA, lambdaMaxA, radialCount, rOutRg, rCorRg,
    useColorCorrection, fColor,
    warm: fWarm, gammaWarm, kTeWarm_keV, EminWarm_keV, EmaxWarm_keV, warmEnergyCount,
    hot: fHot, gammaHot, eCut_keV, EminHot_keV, EmaxHot_keV, hotEnergyCount.

Notes

  • BH mass is in solar masses.
  • Spin is from blackHole%spin().
  • Eddington accretion rate and ISCO radius functions exist in Black_Hole_Fundamentals.

Deliverables

  • A PR against master that adds/updates source/accretion_disks.spectra.disk_corona_intrinsic.F90 with strict energy closure.
  • Ensure code compiles and follows Galacticus coding conventions (use existing constants modules; avoid magic numbers where possible; keep documentation blocks consistent).

Reference file

  • source/accretion_disks.spectra.Hopkins2007.F90 (style reference only).

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: We have just one, kinda old, implementation of an AGN SED model. Since we're working on improving this aspect of the model it would be nice to find some better, more recent model that we could use to add as a new implementation of this class.

Assistant: A good next step is to add at least one modern, modular AGN SED option that (a) is widely used post-2010, (b) has a clean parameterization you can sample over (BH mass, Eddington ratio, obscuration, viewing angle, etc.), and (c) is feasible to ship in Galacticus without relying on a fragile external download/compile at runtime (your current Hopkins2007 implementation literally downloads and builds agn_spectrum.c on demand; see lines ~192–202 in source/accretion_disks.spectra.Hopkins2007.F90).

Here are “better / more recent” families that are commonly used in galaxy/AGN modeling, with a suggestion for what makes sense as a new accretionDiskSpectra... implementation.

1) Physically-motivated accretion disk + corona SEDs (recommended if you want “model”, not just templates)

Done et al. 2012 OPTXAGNF / OPTXCONV

  • What it is: a semi-physical SED model with color-corrected disk + warm Comptonization (soft X-ray excess) + hot corona.
  • Parameters you can naturally connect to your BH module: BH mass, Eddington ratio / Ṁ, spin (optional), coronal radius, coronal fractions, etc.
  • Pros: much more “physics-forward” than Hopkins2007; widely used and cited.
  • Cons: if you want orientation/torus IR you still need an obscurer + reprocessor model on top, or pair with an IR torus library.

How it would fit Galacticus: create accretion_disks.spectra.Done2012.F90 that tab...

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Add strict energy-closure scaling to intrinsic thin-disk AGN SED implementation Add intrinsic three-component thin-disk AGN SED with strict energy-closure scaling Apr 12, 2026
Copilot AI requested a review from abensonca April 12, 2026 23:37
@abensonca abensonca marked this pull request as ready for review April 16, 2026 16:46
@github-actions
Copy link
Copy Markdown

Embedded XML/LaTeX warnings (click to expand)

⚠️ Possible misspelled word 'comptonized' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'coronae' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'normalised' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'comptonized' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'comptonized' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (3 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'giga' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'normalised' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'sed' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'hν' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2t' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'dt' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adafradiative' in file 'source/accretion_disks.switched.F90'

@github-actions
Copy link
Copy Markdown

Embedded XML/LaTeX warnings (click to expand)

⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'normalised' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (3 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'giga' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'sed' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'hν' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2t' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'dt' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adafradiative' in file 'source/accretion_disks.switched.F90'

@github-actions
Copy link
Copy Markdown

Embedded XML/LaTeX warnings (click to expand)

⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (3 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'giga' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'sed' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'hν' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2t' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'dt' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adafradiative' in file 'source/accretion_disks.switched.F90'

@github-actions
Copy link
Copy Markdown

Embedded XML/LaTeX warnings (click to expand)

⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (3 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'giga' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'sed' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'hν' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2t' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'dt' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adafradiative' in file 'source/accretion_disks.switched.F90'

These are read as lists of `numpy` arrays - we convert to simple `numpy` arrays to make them easier to work with.
@github-actions
Copy link
Copy Markdown

Embedded XML/LaTeX warnings (click to expand)

⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (3 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'giga' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'sed' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'hν' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2π' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '4π' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'multitemperature' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word '2t' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'dt' in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'isco' (2 instances) in file 'source/accretion_disks.spectra.thin_disk.F90'
⚠️ Possible misspelled word 'pre' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adaf' in file 'source/accretion_disks.ADAF.F90'
⚠️ Possible misspelled word 'adafradiative' in file 'source/accretion_disks.switched.F90'

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.

2 participants