CLASSpp Manual
Cosmology reference and developer manual
Loading...
Searching...
No Matches
base_species.h
1#pragma once
2
3#include <cstddef>
4#include <memory>
5#include <optional>
6#include <string>
7#include <vector>
8
9#include "shooting_target.h"
10
11// Forward declarations to avoid circular includes
12struct background;
14struct precision;
15struct perturb_vector;
18
19#include "background_ic_context.h"
20#include "common.h" // class_store_columntitle, class_store_double, true, false
21#include "perturb_source_context.h"
22
23class BackgroundModule; // forward declaration
24class ThermodynamicsModule; // forward declaration
25
26// ── BackgroundColumnWriter ───────────────────────────────────────────────────
33 public:
34 explicit BackgroundColumnWriter(std::string& titles) : titles_(&titles) {}
35 BackgroundColumnWriter(double* dataptr, int& storeidx)
36 : dataptr_(dataptr), storeidx_(&storeidx) {}
37
38 bool IsTitleMode() const {
39 return titles_ != nullptr;
40 }
41
42 void Add(const char* title, double value, bool condition = true) {
43 if (titles_) {
44 class_store_columntitle(*titles_, title, condition ? true : false);
45 }
46 else if (dataptr_) {
47 class_store_double(dataptr_, value, condition ? true : false, (*storeidx_));
48 }
49 }
50 void Add(const std::string& title, double value, bool condition = true) {
51 Add(title.c_str(), value, condition);
52 }
53
54 private:
55 std::string* titles_ = nullptr;
56 double* dataptr_ = nullptr;
57 int* storeidx_ = nullptr;
58};
59struct perturbs; // forward declaration
60
77 public:
79 enum class EnergyType { Radiation, Matter, DarkEnergy, Other };
80 enum class TransferColumnSection { all, density, velocity };
81
82 // ── Perturbation layout (per-pv per-species index storage) ───────────────
90 virtual ~PerturbLayout() = default;
91 };
92
99 virtual std::unique_ptr<PerturbLayout> CreatePerturbLayout() const {
100 return std::make_unique<PerturbLayout>();
101 }
102
103 virtual ~BaseSpecies() = default;
104 BaseSpecies(const BaseSpecies&) = delete;
105 BaseSpecies& operator=(const BaseSpecies&) = delete;
106
107 const std::string& name() const {
108 return name_;
109 }
110 EnergyType energy_type() const {
111 return energy_type_;
112 }
113
119 virtual void SetBackgroundModule(const BackgroundModule* /*bgm*/) {}
120
125 virtual void SetThermodynamicsModule(const ThermodynamicsModule* /*thm*/) {}
126
131 virtual void SetPerturbs(const perturbs* /*ppt*/) {}
132
137 virtual std::optional<double> GetParam(const std::string& /*name*/) const {
138 return std::nullopt;
139 }
140
141 // ── Background ────────────────────────────────────────────────────────────
142
148 virtual void RegisterBackgroundIndices(int& index_bg) = 0;
149
154 virtual void RegisterIntegrationIndices(int& index_bi) {}
155
162
168 virtual void ComputeBackground(double a, const double* pvecback_B, double* pvecback) = 0;
169
175 virtual void BackgroundDerivs(double tau, const double* y, double* dy, const double* pvecback) {}
176
178 virtual double Rho(const double* pvecback) const = 0;
179
181 virtual double P(const double* pvecback) const = 0;
182
188 virtual double PPrime(double a,
189 double H,
190 const double* pvecback_B,
191 const double* pvecback) const {
192 return 0.;
193 }
194
199 virtual void FinalizeBackground(double a, double H, const double* pvecback_B, double* pvecback) {}
200
201 // ── Background output ─────────────────────────────────────────────────────
202
209 virtual bool IsFreestreaming() const {
210 return false;
211 }
212
218 virtual double FreestreamingRho(const double* pvecback) const {
219 return IsFreestreaming() ? Rho(pvecback) : 0.;
220 }
221
227 bool IsPresent() const {
228 return index_bg_rho_ >= 0;
229 }
230
236 virtual void WriteBackgroundColumnTitles(BackgroundColumnWriter& /*writer*/) const {}
237
244 virtual void WriteBackgroundData(const double* /*pvecback*/,
245 BackgroundColumnWriter& /*writer*/) const {}
246
251 virtual void ProcessBackgroundTable(const double* /*background_table*/,
252 int /*n_rows*/,
253 int /*row_stride*/,
254 const double* /*z_table*/) {}
255
256 // ── Perturbations ─────────────────────────────────────────────────────────
257
258 // ── Per-species layout signatures ───────────────────────────────────────
259
267 virtual void RegisterTransferSourceIndices(int& /*index_tp*/,
268 const SourceRequestContext& /*ctx*/) {}
269
270 virtual void RegisterPerturbationIndices(PerturbLayout& /*layout*/,
271 perturb_vector* /*pv*/,
272 const precision* /*ppr*/,
273 int& /*index_pt*/,
274 const perturb_workspace* /*ppw*/,
275 int /*gauge*/) {}
276
277 virtual void RegisterVectorPerturbationIndices(PerturbLayout& /*layout*/,
278 perturb_vector* /*pv*/,
279 const precision* /*ppr*/,
280 int& /*index_pt*/,
281 const perturb_workspace* /*ppw*/,
282 int /*gauge*/) {}
283
284 virtual void RegisterTensorPerturbationIndices(PerturbLayout& /*layout*/,
285 perturb_vector* /*pv*/,
286 const precision* /*ppr*/,
287 int& /*index_pt*/,
288 const perturb_workspace* /*ppw*/,
289 int /*gauge*/) {}
290
298 virtual void PerturbDerivs(const PerturbLayout& layout,
299 double tau,
300 const double* y,
301 double* dy,
302 const perturb_parameters_and_workspace& ppaw) const = 0;
303
305 virtual void PerturbVectorDerivs(const PerturbLayout& /*layout*/,
306 double /*tau*/,
307 const double* /*y*/,
308 double* /*dy*/,
309 const perturb_parameters_and_workspace& /*ppaw*/) const {}
310
312 virtual void PerturbTensorDerivs(const PerturbLayout& /*layout*/,
313 double /*tau*/,
314 const double* /*y*/,
315 double* /*dy*/,
316 const perturb_parameters_and_workspace& /*ppaw*/) const {}
317
319 virtual void WriteTensorOutputColumnTitles(std::string& /*tensor_titles*/) const {}
320
324 virtual void ContributeTensorGwSource(const PerturbLayout& /*layout*/,
325 double /*a*/,
326 const double* /*y*/,
327 perturb_workspace* /*ppw*/) const {}
328
333 double rho = 0.; // background ρ
334 double p = 0.; // background P
335 double delta_rho = 0.; // δρ
336 double rho_plus_p_theta = 0.; // (ρ+P)θ
337 double delta_p = 0.; // δp
338 double rho_plus_p_shear = 0.; // (ρ+P)σ
339
341 rho += o.rho;
342 p += o.p;
343 delta_rho += o.delta_rho;
344 rho_plus_p_theta += o.rho_plus_p_theta;
345 delta_p += o.delta_p;
346 rho_plus_p_shear += o.rho_plus_p_shear;
347 return *this;
348 }
349 };
350
353 const perturb_vector* pv,
354 const double* y,
355 const double* pvecback,
356 const perturb_workspace* ppw) const = 0;
357
358 // ── Stress-energy + matter tally (hot path) ───────────────────────────────
359 // Non-virtual wrapper, inlined at the loop call site (e.species is BaseSpecies*).
360 // Plain species: one virtual call (StressEnergy) + accumulate. Composites set
361 // delegates_tally_ and forward the WHOLE call per child via DelegateTally, so each
362 // child is evaluated exactly once. The three accumulators are owned by the module
363 // loop; StressEnergyContribution::operator+= is reused as the bucket combiner.
364 // ppw is only passed through to StressEnergy (never dereferenced), so this compiles
365 // with perturb_workspace forward-declared.
366 void TallyStressEnergy(const PerturbLayout& layout,
367 const perturb_vector* pv,
368 const double* y,
369 const double* pvecback,
370 const perturb_workspace* ppw,
372 StressEnergyContribution& total_cold,
373 StressEnergyContribution& total_warm) const {
374 if (delegates_tally_) {
375 DelegateTally(layout, pv, y, pvecback, ppw, total, total_cold, total_warm);
376 return;
377 }
378 const StressEnergyContribution se = StressEnergy(layout, pv, y, pvecback, ppw);
379 total += se;
380 // Actual ρ/δρ/(ρ+P)θ — no ρ−3P proxy. Radiation never reaches here (it does not
381 // cluster as matter), so there is nothing to "zero out".
382 if (clusters_as_matter_)
383 (is_cold_ ? total_cold : total_warm) += se;
384 }
385
386 // Seam: only composites (delegates_tally_ == true) override this; plain species
387 // never reach the base body.
388 virtual void DelegateTally(const PerturbLayout& /*layout*/,
389 const perturb_vector* /*pv*/,
390 const double* /*y*/,
391 const double* /*pvecback*/,
392 const perturb_workspace* /*ppw*/,
393 StressEnergyContribution& /*total*/,
394 StressEnergyContribution& /*total_cold*/,
395 StressEnergyContribution& /*total_warm*/) const {}
396
397 // ── Stage 1: Output ──────────────────────────────────────────────────────
398
406 virtual void WriteOutputColumns(
407 PerturbColumnWriter& /*writer*/,
408 const PerturbationsModule& /*mod*/,
409 file_format /*fmt*/,
410 TransferColumnSection /*section*/ = TransferColumnSection::all) const {}
411
419 virtual void PrintVariables(PerturbColumnWriter& /*writer*/,
420 double /*tau*/,
421 const double* /*y*/,
422 const PerturbationsModule& /*mod*/,
423 const perturb_workspace* /*ppw*/) const {}
424
425 // ── Stage 2: Source filling ───────────────────────────────────────────────
426
435 virtual void FillSources(const PerturbLayout& /*layout*/,
436 const double* /*y*/,
437 const double* /*dy*/,
438 PerturbSourceContext& /*ctx*/) const {}
439
440 // ── Stage 3: Initial conditions ───────────────────────────────────────────
441
449 virtual void ApplyInitialConditions(const PerturbLayout& /*layout*/,
450 double* /*y*/,
451 const PerturbIcContext& /*ctx*/) {}
452
459 virtual void CopyPerturbationsAcrossSwitch(const PerturbLayout& /*old_layout*/,
460 const PerturbLayout& /*new_layout*/,
461 const double* /*old_y*/,
462 double* /*new_y*/,
463 const PerturbSwitchContext& /*ctx*/) const {}
464
465 // ── Synchronous → Newtonian gauge transformation ──────────────────────────
474 virtual double RhoDotOverRho(const double* pvecback, double a_prime_over_a) const {
475 return -3. * a_prime_over_a * (Rho(pvecback) + P(pvecback)) / Rho(pvecback);
476 }
477
485 virtual void PerturbSynchronousToNewtonian(const PerturbLayout& /*layout*/,
486 double* /*y*/,
487 const PerturbIcContext& /*ctx*/) {}
488
489 // ── Shooter / root-finding ────────────────────────────────────────────────
490 // Reported after construction; non-empty iff this species guessed its unknown
491 // (target-form input set, direct unknown absent). Drives target detection, the
492 // unknown vector, and the lazy-shooting trigger.
493 virtual std::vector<ShootingTarget> GetShootingTargets() const {
494 return {};
495 }
496 // Initial guess + Jacobian seed for each unknown, same order as GetShootingTargets.
497 // Also called by CreateAll to obtain the value to build from when the unknown is absent.
498 virtual void ComputeShootingGuess(const SpeciesBuildContext& /*ctx*/,
499 std::vector<double>& /*guess*/,
500 std::vector<double>& /*dxdy*/) const {}
501 // computed-today minus the requested target. The authoritative target is supplied by
502 // the shooter (collected once at discovery), so the species never re-derives it from
503 // the file content — in iteration builds DoShooting has set the unknown, which for some
504 // species (e.g. DCDM_DR's overlapping Omega_dcdmdr/Omega_ini_dcdm) makes the user's
505 // target indistinguishable by key presence.
506 virtual double ComputeShootingResidual(const ShootingResidualContext& /*ctx*/,
507 const ShootingTarget& /*target*/) const {
508 return 0.;
509 }
510
517 virtual void MarkUsedInSources(const PerturbLayout& /*layout*/,
518 const perturb_workspace* /*ppw*/,
519 int* /*used_in_sources*/) const {}
520
521 virtual void MarkVectorUsedInSources(const PerturbLayout& /*layout*/,
522 const perturb_workspace* /*ppw*/,
523 int* /*used_in_sources*/) const {}
524
525 virtual void MarkTensorUsedInSources(const PerturbLayout& /*layout*/,
526 const perturb_workspace* /*ppw*/,
527 int* /*used_in_sources*/) const {}
528
534 virtual double GetOmega0() const = 0;
535
538 virtual double GetRadiationOmega0() const {
539 return 0.;
540 }
541
542 // ── NCDM/DR-family hooks (#308) ───────────────────────────────────────────
543 // Neutral defaults let modules loop over all_species_ and call these directly
544 // instead of downcasting; composites forward/sum over their children.
545
548 virtual double DarkRadiationRhoToday(const double* /*pvecback_integration*/) const {
549 return 0.;
550 }
551
554 virtual double NeutrinoOmega0() const {
555 return 0.;
556 }
557
560 virtual double NeffContribution(double /*z*/) const {
561 return 0.;
562 }
563
566 virtual void PrintNeffInfo() const {}
569 virtual void PrintMassInfo() const {}
570
573 virtual double TensorMasslessRelativisticRho(const double* /*pvecback*/) const {
574 return 0.;
575 }
576
579 virtual void CheckUltraRelativisticAtIc(const double* /*pvecback*/, double /*tol*/) const {}
580
583 virtual bool IsUltraRelativisticAtIc(const double* /*pvecback*/, double /*tol*/) const {
584 return true;
585 }
586
590 virtual void WarnIfTooHeavyForHalofit(double /*m_ev_threshold*/) const {}
591
594 virtual double BackgroundAIni(double a_proposed, double /*tol*/) const {
595 return a_proposed;
596 }
597
601 return clusters_as_matter_;
602 }
603 bool IsColdCached() const {
604 return is_cold_;
605 }
606
611 clusters_as_matter_ = ClustersAsMatter();
612 is_cold_ = IsColdMatterSpecies();
613 }
614
628 virtual bool ClustersAsMatter() const {
629 return energy_type_ == EnergyType::Matter;
630 }
631
638 virtual bool IsColdMatterSpecies() const {
639 return energy_type_ == EnergyType::Matter;
640 }
641
651 virtual bool HasWarmMatter() const {
653 }
654
655 protected:
656 BaseSpecies(std::string name, EnergyType energy_type)
657 : name_(std::move(name)), energy_type_(energy_type) {}
658
665 int idx_delta,
666 int idx_theta,
667 const double* pvecback,
668 const PerturbIcContext& ctx) const {
669 if (idx_delta >= 0)
670 y[idx_delta] += RhoDotOverRho(pvecback, ctx.a_prime_over_a) * ctx.alpha;
671 if (idx_theta >= 0)
672 y[idx_theta] += ctx.k * ctx.k * ctx.alpha;
673 }
674
675 std::string name_;
676 EnergyType energy_type_;
677
678 // Cached matter-tally classification, stamped once by FinalizeMatterClassification()
679 // (driven by SpeciesCollection::freeze(); composites recurse into children). Read on
680 // the stress-energy hot path, so it must be a plain member, not a per-step virtual.
681 bool clusters_as_matter_ = false;
682 bool is_cold_ = false;
683 bool delegates_tally_ = false; // true for composites (set in CompositeSpecies ctor)
684
685 // Set by SpeciesCollection::freeze(); used by PrintVariables to look up layout.
686 std::size_t collection_index_ = SIZE_MAX;
687
688 // Set by RegisterBackgroundIndices(); -1 means "not registered / species absent"
689 int index_bg_rho_ = -1;
690 int index_bg_p_ = -1; // only set by species that store p separately (e.g. NCDM)
691
692 friend class SpeciesCollection;
693};
694
695// ── Background budget printout (background_verbose > 1) ───────────────────────
696// Coarse presentation buckets for background_output_budget(). Distinct from
697// EnergyType because NCDM-family species are EnergyType::Other yet warrant their
698// own section, and composites (also EnergyType::Other) split across buckets by
699// child.
700enum class BudgetBucket { Radiation, NonRelativistic, Ncdm, Other };
701
702// One printed budget line: a (sub-)species' today density fraction and its bucket.
703struct BudgetLine {
704 std::string label;
705 double omega;
706 BudgetBucket bucket;
707};
708
709// Classify a species into a budget bucket. NCDM-family -> Ncdm (the same family
710// test GetNcdmSpecies uses); otherwise mapped from energy_type(). Defined in
711// base_species.cpp.
712BudgetBucket BudgetBucketOf(const BaseSpecies& s);
Definition base_species.h:32
Definition base_species.h:76
virtual void BackgroundDerivs(double tau, const double *y, double *dy, const double *pvecback)
Definition base_species.h:175
virtual double BackgroundAIni(double a_proposed, double) const
Definition base_species.h:594
virtual void ApplyInitialConditions(const PerturbLayout &, double *, const PerturbIcContext &)
Definition base_species.h:449
virtual void FinalizeBackground(double a, double H, const double *pvecback_B, double *pvecback)
Definition base_species.h:199
virtual bool HasWarmMatter() const
Definition base_species.h:651
bool ClustersAsMatterCached() const
Definition base_species.h:600
virtual double PPrime(double a, double H, const double *pvecback_B, const double *pvecback) const
Definition base_species.h:188
virtual void FinalizeMatterClassification()
Definition base_species.h:610
virtual double NeffContribution(double) const
Definition base_species.h:560
virtual void PerturbSynchronousToNewtonian(const PerturbLayout &, double *, const PerturbIcContext &)
Definition base_species.h:485
virtual double GetRadiationOmega0() const
Definition base_species.h:538
virtual void CopyPerturbationsAcrossSwitch(const PerturbLayout &, const PerturbLayout &, const double *, double *, const PerturbSwitchContext &) const
Definition base_species.h:459
virtual void SetPerturbs(const perturbs *)
Definition base_species.h:131
virtual std::unique_ptr< PerturbLayout > CreatePerturbLayout() const
Definition base_species.h:99
virtual void FillSources(const PerturbLayout &, const double *, const double *, PerturbSourceContext &) const
Definition base_species.h:435
virtual void PrintVariables(PerturbColumnWriter &, double, const double *, const PerturbationsModule &, const perturb_workspace *) const
Definition base_species.h:419
virtual void MarkUsedInSources(const PerturbLayout &, const perturb_workspace *, int *) const
Definition base_species.h:517
virtual void RegisterIntegrationIndices(int &index_bi)
Definition base_species.h:154
virtual void ComputeBackground(double a, const double *pvecback_B, double *pvecback)=0
virtual bool IsUltraRelativisticAtIc(const double *, double) const
Definition base_species.h:583
virtual bool ClustersAsMatter() const
Definition base_species.h:628
virtual double NeutrinoOmega0() const
Definition base_species.h:554
bool IsPresent() const
Definition base_species.h:227
virtual void WriteBackgroundData(const double *, BackgroundColumnWriter &) const
Definition base_species.h:244
virtual void SetThermodynamicsModule(const ThermodynamicsModule *)
Definition base_species.h:125
virtual double RhoDotOverRho(const double *pvecback, double a_prime_over_a) const
Definition base_species.h:474
virtual double GetOmega0() const =0
virtual void WriteBackgroundColumnTitles(BackgroundColumnWriter &) const
Definition base_species.h:236
virtual void PerturbTensorDerivs(const PerturbLayout &, double, const double *, double *, const perturb_parameters_and_workspace &) const
Definition base_species.h:312
virtual void ProcessBackgroundTable(const double *, int, int, const double *)
Definition base_species.h:251
virtual double P(const double *pvecback) const =0
virtual void SetBackgroundModule(const BackgroundModule *)
Definition base_species.h:119
virtual void RegisterTransferSourceIndices(int &, const SourceRequestContext &)
Definition base_species.h:267
virtual void CheckUltraRelativisticAtIc(const double *, double) const
Definition base_species.h:579
virtual bool IsFreestreaming() const
Definition base_species.h:209
virtual void PerturbVectorDerivs(const PerturbLayout &, double, const double *, double *, const perturb_parameters_and_workspace &) const
Definition base_species.h:305
virtual void WriteOutputColumns(PerturbColumnWriter &, const PerturbationsModule &, file_format, TransferColumnSection=TransferColumnSection::all) const
Definition base_species.h:406
virtual void PerturbDerivs(const PerturbLayout &layout, double tau, const double *y, double *dy, const perturb_parameters_and_workspace &ppaw) const =0
virtual void PrintNeffInfo() const
Definition base_species.h:566
virtual void ContributeTensorGwSource(const PerturbLayout &, double, const double *, perturb_workspace *) const
Definition base_species.h:324
virtual double DarkRadiationRhoToday(const double *) const
Definition base_species.h:548
EnergyType
Definition base_species.h:79
virtual void RegisterBackgroundIndices(int &index_bg)=0
void ApplyFluidLikeNewtonianShift(double *y, int idx_delta, int idx_theta, const double *pvecback, const PerturbIcContext &ctx) const
Definition base_species.h:664
virtual bool IsColdMatterSpecies() const
Definition base_species.h:638
virtual std::optional< double > GetParam(const std::string &) const
Definition base_species.h:137
virtual double Rho(const double *pvecback) const =0
virtual void WriteTensorOutputColumnTitles(std::string &) const
Definition base_species.h:319
virtual double FreestreamingRho(const double *pvecback) const
Definition base_species.h:218
virtual double TensorMasslessRelativisticRho(const double *) const
Definition base_species.h:573
virtual StressEnergyContribution StressEnergy(const PerturbLayout &layout, const perturb_vector *pv, const double *y, const double *pvecback, const perturb_workspace *ppw) const =0
virtual void PrintMassInfo() const
Definition base_species.h:569
virtual void WarnIfTooHeavyForHalofit(double) const
Definition base_species.h:590
virtual void SetBackgroundInitialConditions(const BackgroundICContext &ctx)
Definition base_species.h:161
Definition perturb_source_context.h:63
Definition species_collection.h:33
Definition perturbations.h:250
Definition perturbations.h:344
Definition perturbations.h:100
file_format
Definition precision.h:40
Definition background_ic_context.h:11
Definition base_species.h:89
Definition base_species.h:332
Definition perturb_source_context.h:125
Definition perturb_source_context.h:103
Definition perturb_source_context.h:159
Definition shooting_target.h:7
Definition shooting_target.h:14
Definition perturb_source_context.h:48
Definition species_build_context.h:58
Definition perturbations_module.h:341
Definition precision.h:63