public void AddDimensionedSpecies(SpeciesValue species, double molarity, double molarityVariance, string dimension, double volume, Style style) { if (this.HasSpecies(species.symbol, out int index)) { throw new Error("Repeated amount of '" + species.Format(style) + "' in sample '" + this.sample.Format(style) + "' with value " + style.FormatDouble(molarity)); } else if (molarity < 0) { throw new Error("Amount of '" + species.Format(style) + "' in sample '" + this.sample.Format(style) + "' must be non-negative: " + style.FormatDouble(molarity)); } else if (molarityVariance < 0) { throw new Error("Variance of amount of '" + species.Format(style) + "' in sample '" + this.sample.Format(style) + "' must be non-negative: " + style.FormatDouble(molarityVariance)); } else { this.species.Add(species); RecomputeIndex(); this.state = this.state.Extend(1); this.state.SumMean(this.state.size - 1, NormalizeDimension(species, molarity, dimension, volume, style)); if (this.state.lna) { this.state.SumCovar(this.state.size - 1, this.state.size - 1, NormalizeDimension(species, molarityVariance, dimension, volume, style)); // may normalize variance by volume } } }
//public void Transfer(StateMap other, double thisVolume, double otherVolume, Style style) { // // transfer from another stateMap into this (empty) one // // if new volume is larger, then it is "dilution", and it the same as mixing with an empty sample // // but if new volume is smaller, then it is "evaporation", which cannot be otherwise expressed // int n = 0; // foreach (SpeciesValue otherSpecies in other.species) { // this.species.Add(otherSpecies); // n++; // } // RecomputeIndex(); // if (n > 0) this.state = this.state.Extend(n); // // if volumeScaling==0 then volume will be 0 so it does not matter what mean and covar are // foreach (SpeciesValue otherSpecies in other.species) { // SumMean(otherSpecies.symbol, (proportion == 0.0) ? 0.0 : other.Mean(otherSpecies.symbol)/proportion); // double squareProportion = proportion * proportion; // square of volume ratio law, // if (this.state.lna && other.state.lna) { // foreach (SpeciesValue otherSpecies2 in other.species) { // double otherCovar = (proportion == 0.0) ? 0.0 : other.Covar(otherSpecies.symbol, otherSpecies2.symbol) / squareProportion; // SumCovar(otherSpecies.symbol, otherSpecies2.symbol, otherCovar); // } // } // } //} public double NormalizeDimension(SpeciesValue species, double value, string dimension, double volume, Style style) { if (double.IsNaN(value)) { return(value); } double normal; normal = Protocol.NormalizeMolarity(value, dimension); if (normal >= 0) { return(normal); // value had dimension M = mol/L } normal = Protocol.NormalizeMole(value, dimension); if (normal >= 0) { return(normal / volume); // value had dimension mol, convert it to M = mol/L } normal = Protocol.NormalizeWeight(value, dimension); if (normal >= 0) { if (species.HasMolarMass()) { return((normal / species.MolarMass()) / volume); // value had dimension g, convert it to M = (g/(g/M))/L } throw new Error("Species '" + species.Format(style) + "' was given no molar mass, hence its amount in sample '" + this.sample.Format(style) + "' should have dimension 'M' (concentration) or 'mol' (mole), not '" + dimension + "'"); } throw new Error("Invalid dimension '" + dimension + "'" + " or dimension value " + style.FormatDouble(value)); }
public override string Format(Style style) { string s = "trigger "; s += target.Format(style) + " @ "; s += assignment.TopFormat(style) + " "; s += (assignmentVariance == null) ? "" : " ± " + assignmentVariance.Format(style) + " "; s += dimension + " when "; s += condition.TopFormat(style); s += sample.symbol.IsVesselVariant() ? "" : " in " + sample.FormatSymbol(style); return(s); }
public (SpeciesFlow[, ], Flow[, ]) CovarFlow(Style style) { int speciesNo = sample.Count(); SpeciesFlow[,] covar = new SpeciesFlow[speciesNo, speciesNo]; // fill it with fresh covariance variables for (int speciesI = 0; speciesI < speciesNo; speciesI++) // rows { SpeciesValue variableI = sample.stateMap.species[speciesI]; for (int speciesJ = 0; speciesJ < speciesNo; speciesJ++) // columns { SpeciesValue variableJ = sample.stateMap.species[speciesJ]; if (style.exportTarget == ExportTarget.WolframNotebook) { covar[speciesI, speciesJ] = new SpeciesFlow(new Symbol(variableI.Format(style) + "_" + variableJ.Format(style))); } else { covar[speciesI, speciesJ] = (speciesI == speciesJ) ? new SpeciesFlow(new Symbol("var(" + variableI.Format(style) + ")")) : new SpeciesFlow(new Symbol("cov(" + variableI.Format(style) + "," + variableJ.Format(style) + ")")); } } } Flow[,] covarFlow = new Flow[speciesNo, speciesNo]; Flow[,] jacobian = Jacobian(style); Flow[,] drift = Drift(); for (int speciesI = 0; speciesI < speciesNo; speciesI++) // rows { for (int speciesJ = 0; speciesJ < speciesNo; speciesJ++) // columns { covarFlow[speciesI, speciesJ] = NumberFlow.numberFlowZero; for (int speciesK = 0; speciesK < speciesNo; speciesK++) // dot product index { covarFlow[speciesI, speciesJ] = OpFlow.Op("+", covarFlow[speciesI, speciesJ], OpFlow.Op("*", jacobian[speciesI, speciesK], covar[speciesK, speciesJ])); covarFlow[speciesI, speciesJ] = OpFlow.Op("+", covarFlow[speciesI, speciesJ], OpFlow.Op("*", jacobian[speciesJ, speciesK], covar[speciesI, speciesK])); // jacobian transposed } covarFlow[speciesI, speciesJ] = OpFlow.Op("+", covarFlow[speciesI, speciesJ], drift[speciesI, speciesJ]); } } return(covar, covarFlow); }
public override string Format(Style style) { return("amount " + species.Format(style) + " @ " + initial.Format(style) + ((initialVariance is NumberValue num && num.value == 0.0) ? "" : " ± " + initialVariance.Format(style)) + " " + dimension + " in " + sample.FormatSymbol(style)); }