public void AddGallons(string name, double numGallons) { double liters = K.litersPerGallon * numGallons; MaterialType mt = m_brs.MyMaterialCatalog[name]; double kg = liters * mt.SpecificGravity; m_initialMixture.AddMaterial(mt.CreateMass(kg, m_tempOfTankLiquidInitial)); m_initialMixture.Temperature = m_initialMixtureTemperature; m_currentMixture = (Mixture)m_initialMixture.Clone(); }
/// <summary> /// Sets the initial mixture in the modeled vessel. /// </summary> /// <param name="initial">The initial mixture in the modeled vessel.</param> public void SetInitialMixture(Mixture initial) { if (initial != null) { m_initial = (Mixture)initial.Clone(); } else { m_initial = new Mixture(); } }
/// <summary> /// Sets the inflowing mixture in the modeled vessel. /// </summary> /// <param name="inflow">The inflowing mixture in the modeled vessel.</param> public void SetInflowMixture(Mixture inflow) { if (inflow != null) { m_inflow = (Mixture)inflow.Clone(); } else { m_inflow = new Mixture(); } }
/// <summary> /// Sets the outflowing mixture in the modeled vessel. /// </summary> /// <param name="outflow">The outflowing mixture in the modeled vessel.</param> public void SetOutflowMixture(Mixture outflow) { if (outflow != null) { m_outflow = (Mixture)outflow.Clone(); } else { m_outflow = new Mixture(); } }
/// <summary> /// Creates a MVTracker with a full complement of parameters. /// </summary> /// <param name="initial">The initial mixture.</param> /// <param name="inflow">The inflowing mixture.</param> /// <param name="outflow">The outflowing mixture.</param> /// <param name="capacity">The capacity of the vessel.</param> /// <param name="rp">The ReactionProcessor that knows of any reactions that will take place. Can be null.</param> public MassVolumeTracker(Mixture initial, Mixture inflow, Mixture outflow, double capacity, ReactionProcessor rp) { m_massHistory = new DoubleTracker(); m_volumeHistory = new DoubleTracker(); SetInitialMixture(initial == null ? new Mixture() : (Mixture)initial.Clone()); SetInflowMixture(inflow == null ? new Mixture() : (Mixture)inflow.Clone()); SetOutflowMixture(outflow == null ? new Mixture() : (Mixture)outflow.Clone()); m_reactionProcessor = rp; m_capacity = capacity; m_cyclical = true; m_inflowFirst = true; }
public void ProcessEmissions( Mixture initial, out Mixture final, out Mixture emission, bool modifyInPlace, string emissionModelKey, Hashtable parameters) { final = null; emission = null; IEmissionModel em = (IEmissionModel)m_models[emissionModelKey]; if (em == null) { if (!m_ignoreUnknownModelTypes) { string msg = "Emission Model Key \"" + emissionModelKey + "\" does not match known emission model keys, which include "; msg += Utility.StringOperations.ToCommasAndAndedList(new ArrayList(m_models.Keys)); throw new ApplicationException(msg); } } else { if (m_enabled) { em.Process(initial, out final, out emission, modifyInPlace, parameters); } else { final = (Mixture)initial.Clone(); emission = new Mixture(); } } }
/// <summary> /// Performs the inflow/outflow cycle analysis. After this runs, consult the Mass, Volume and Temperature history members. /// </summary> public void Process() { m_massHistory.Reset(); m_volumeHistory.Reset(); Mixture contents = (Mixture)m_initial.Clone(); if (m_reactionProcessor != null) { m_reactionProcessor.Watch(contents); } Mixture inflow = m_inflow == null?new Mixture():(Mixture)m_inflow.Clone(); Mixture outflow = m_outflow == null ? new Mixture() : (Mixture)m_outflow.Clone(); double tiv = inflow.Volume; double tim = inflow.Mass; double tov = outflow.Volume; double tom = outflow.Mass; bool useMinidumps = true; //bool useMinidumps = false; //if ( ( tiv + contents.Volume - tov > m_capacity ) ) useMinidumps = true; RecordMvt(contents); if (m_cyclical) { if (m_inflowFirst) { if (s_diagnostics) { Console.WriteLine("Initial - total volume = " + contents.Volume + ", mixture is " + contents); } while (inflow.Mass > 0.0 || outflow.Mass > 0.0) { // Perform charge if (inflow.Mass > 0.0) { double chgMass = Math.Min((m_capacity - contents.Volume) * (tim / tiv), inflow.Mass); double pctOfInFlow = chgMass / inflow.Mass; contents.AddMaterial(inflow.RemoveMaterial(chgMass)); if (s_diagnostics) { Console.WriteLine("After charge - total volume = " + contents.Volume + ", mixture is " + contents); } RecordMvt(contents); } // Perform discharge if (outflow.Mass > 0.0) { double dischgMass = Math.Min((m_capacity - contents.Volume) * (tom / tov), outflow.Mass); Mixture extract = (Mixture)outflow.RemoveMaterial(dischgMass); foreach (Substance substance in extract.Constituents) { contents.RemoveMaterial(substance.MaterialType, extract.Mass); } if (s_diagnostics) { Console.WriteLine("After discharge - total volume = " + contents.Volume + ", mixture is " + contents); } RecordMvt(contents); } if (useMinidumps) { contents.Clear(); } } } else { throw new NotImplementedException("Only able to model inflow-first, cyclical behavior."); } } else { throw new NotImplementedException("Only able to model inflow-first, cyclical behavior."); } if (m_reactionProcessor != null) { m_reactionProcessor.Ignore(contents); } }
/// <summary> /// Causes the reaction to take place, if possible, in (and perform modifications to, the provided target mixture. /// </summary> /// <param name="target">The target.</param> /// <returns></returns> public ReactionInstance React(Mixture target) { // We will handle a reaction's completion percentage/equilibrium // calculation by first using the reverse reaction to move all of // the already-existent (in proportion) products over to the // reactant side, and then move rxnPct % back to the product side. double fwdScale = double.MaxValue; double revScale = double.MaxValue; if (m_reactants.Count != 0) { foreach (ReactionParticipant rp in m_reactants) { double howMuch = target.ContainedMassOf(rp.MaterialType); if (howMuch > 0 && rp.IsCatalyst) { howMuch = double.MaxValue; } fwdScale = Math.Min(fwdScale, howMuch / rp.Mass); if (s_diagnostics) { _Debug.WriteLine("target contains " + howMuch + " of reactant " + rp.MaterialType.Name + " so fwdScale is " + fwdScale); } } if (fwdScale == double.MaxValue) { fwdScale = 0.0; } } else { fwdScale = 0.0; } fwdScale *= m_rxPct; if (m_products.Count != 0) { foreach (ReactionParticipant rp in m_products) { double howMuch = target.ContainedMassOf(rp.MaterialType); if (howMuch > 0 && rp.IsCatalyst) { howMuch = double.MaxValue; } revScale = Math.Min(revScale, howMuch / rp.Mass); if (s_diagnostics) { _Debug.WriteLine("target contains " + howMuch + " of product " + rp.MaterialType.Name + " so revScale is " + revScale); } } if (revScale == double.MaxValue) { revScale = 0.0; } } else { revScale = 0.0; } revScale *= (1 - m_rxPct); // If we're going to undo and then redo the same thing, the reaction didn't happen. if ((fwdScale == 0.0 && revScale == 0.0) || (Math.Abs(fwdScale - revScale) < 0.000001)) { if (s_diagnostics) { _Debug.WriteLine("Reaction " + Name + " won't happen in mixture " + target); } return(null); } if (s_diagnostics) { _Debug.WriteLine("Mixture is " + target); } if (s_diagnostics) { _Debug.WriteLine("Reaction " + Name + " is happening. " + ToString()); } ReactionGoingToHappenEvent?.Invoke(this, target); target.ReactionGoingToHappen(this); Mixture mixtureWas = (Mixture)target.Clone(); target.SuspendChangeEvents(); if (s_diagnostics) { _Debug.WriteLine(revScale > 0.0 ? "Performing reverse reaction..." : "Reverse reaction won't happen."); } if (revScale > 0.0) { React(target, m_products, m_reactants, revScale); } if (s_diagnostics) { _Debug.WriteLine(fwdScale > 0.0 ? "Performing forward reaction..." : "Forward reaction won't happen."); } if (fwdScale > 0.0) { React(target, m_reactants, m_products, fwdScale * m_rxPct); } // Percent completion is pulled out of the Reaction object. ReactionInstance ri = new ReactionInstance(this, fwdScale, revScale, m_nextRiGuid); m_nextRiGuid = GuidOps.Increment(m_nextRiGuid); ReactionHappenedEvent?.Invoke(ri); target.ReactionHappened(ri); target.AddEnergy(m_energy * (fwdScale - revScale)); target.ResumeChangeEvents(!mixtureWas.ToString("F2", "F3").Equals(target.ToString("F2", "F3"))); // Only emit summary events if the mixture has changed. return(ri); }
/// <summary> /// Gets a mixture distribution modeled /// by this Gaussian Mixture Model. /// </summary> public Mixture <NormalDistribution> GetMixtureDistribution() { return((Mixture <NormalDistribution>)model.Clone()); }