40 auto logger = LogManager::getInstance().getLogger(
"log");
42 std::vector<Species> speciesToPrime;
43 for (
const auto &entry: netIn.
composition | std::views::values) {
44 if (entry.mass_fraction() == 0.0) {
45 speciesToPrime.push_back(entry.isotope());
48 LOG_DEBUG(logger,
"Priming {} species in the network.", speciesToPrime.size());
51 if (speciesToPrime.empty()) {
59 const double rho = netIn.
density;
66 std::unordered_map<Species, double> currentMassFractions;
67 for (
const auto& entry : netIn.
composition | std::views::values) {
68 currentMassFractions[entry.isotope()] = entry.mass_fraction();
70 for (
const auto& entry : speciesToPrime) {
71 currentMassFractions[entry] = 0.0;
74 std::unordered_map<Species, double> totalMassFractionChanges;
78 for (
const auto& primingSpecies : speciesToPrime) {
79 LOG_TRACE_L3(logger,
"Priming species: {}", primingSpecies.name());
83 for(
const auto& [sp, mf] : currentMassFractions) {
84 tempComp.registerSymbol(std::string(sp.name()));
85 if (mf < 0.0 && std::abs(mf) < 1e-16) {
86 tempComp.setMassFraction(sp, 0.0);
88 tempComp.setMassFraction(sp, mf);
91 tempComp.finalize(
true);
93 NetIn tempNetIn = netIn;
99 LOG_ERROR(logger,
"No priming reactions found for species {}.", primingSpecies.name());
108 double equilibriumMassFraction = 0.0;
110 if (destructionRateConstant > 1e-99) {
112 equilibriumMassFraction = (creationRate / destructionRateConstant) * primingSpecies.mass();
113 if (std::isnan(equilibriumMassFraction)) {
114 LOG_WARNING(logger,
"Equilibrium mass fraction for {} is NaN. Setting to 0.0. This is likely not an issue. It probably originates from all reactions leading to creation and destruction being frozen out. In that case 0.0 should be a good approximation. Hint: This happens often when the network temperature is very the low. ", primingSpecies.name());
115 equilibriumMassFraction = 0.0;
117 LOG_TRACE_L3(logger,
"Found equilibrium for {}: X_eq = {:.4e}", primingSpecies.name(), equilibriumMassFraction);
121 if (dominantChannel) {
122 LOG_TRACE_L3(logger,
"Dominant creation channel for {}: {}", primingSpecies.name(), dominantChannel->
peName());
124 double totalReactantMass = 0.0;
125 for (
const auto& reactant : dominantChannel->
reactants()) {
126 totalReactantMass += reactant.mass();
129 double scalingFactor = 1.0;
130 for (
const auto& reactant : dominantChannel->
reactants()) {
131 const double massToSubtract = equilibriumMassFraction * (reactant.mass() / totalReactantMass);
132 double availableMass = 0.0;
133 if (currentMassFractions.contains(reactant)) {
134 availableMass = currentMassFractions.at(reactant);
136 if (massToSubtract > availableMass && availableMass > 0) {
137 scalingFactor = std::min(scalingFactor, availableMass / massToSubtract);
141 if (scalingFactor < 1.0) {
142 LOG_WARNING(logger,
"Priming for {} was limited by reactant availability. Scaling transfer by {:.4e}", primingSpecies.name(), scalingFactor);
143 equilibriumMassFraction *= scalingFactor;
147 totalMassFractionChanges[primingSpecies] += equilibriumMassFraction;
148 currentMassFractions[primingSpecies] += equilibriumMassFraction;
150 for (
const auto& reactant : dominantChannel->
reactants()) {
151 const double massToSubtract = equilibriumMassFraction * (reactant.mass() / totalReactantMass);
152 totalMassFractionChanges[reactant] -= massToSubtract;
153 currentMassFractions[reactant] -= massToSubtract;
156 LOG_ERROR(logger,
"Failed to find dominant creation channel for {}.", primingSpecies.name());
158 totalMassFractionChanges[primingSpecies] += 1e-40;
159 currentMassFractions[primingSpecies] += 1e-40;
162 LOG_WARNING(logger,
"No destruction channel found for {}. Using fallback abundance.", primingSpecies.name());
163 totalMassFractionChanges[primingSpecies] += 1e-40;
164 currentMassFractions[primingSpecies] += 1e-40;
170 std::vector<std::string> final_symbols;
171 std::vector<double> final_mass_fractions;
172 for(
const auto& [species, mass_fraction] : currentMassFractions) {
173 final_symbols.push_back(std::string(species.name()));
174 if (mass_fraction < 0.0 && std::abs(mass_fraction) < 1e-16) {
175 final_mass_fractions.push_back(0.0);
177 final_mass_fractions.push_back(mass_fraction);
182 Composition primedComposition(final_symbols, final_mass_fractions,
true);
185 for (
const auto& [species, change] : totalMassFractionChanges) {