public override SettingResponseData setSourceValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, bool lastTime) { SettingResponseData ret = new SettingResponseData(); finalFlow -= flowVolume; if(lastTime) { currentVolume -= flowVolume * PhysTools.timeStep; } ret.flowVolume = flowVolume; ret.fluidTypeMap = currentFluidTypeMap; ret.temperature = currentTemperature; inletTemperature = currentTemperature; outletTemperature = currentTemperature; return ret; }
public override void setDeliveryValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, bool lastTime) { finalFlow += flowVolume; if(lastTime) { double volumeToAdd = flowVolume * PhysTools.timeStep; SettingResponseData tankCurrentFluids = new SettingResponseData(currentTemperature, this.currentFluidTypeMap); SettingResponseData incomingFluids = new SettingResponseData(baseData.temperature, baseData.fluidTypeMap); SettingResponseData mixture = PhysTools.mixFluidPercentsAndTemperatures(new SettingResponseData[] { tankCurrentFluids, incomingFluids }, new double[] { currentVolume, volumeToAdd }); this.currentTemperature = mixture.temperature; this.currentFluidTypeMap = mixture.fluidTypeMap; if(isSealed) { currentVolume += volumeToAdd; //Now, we need to calculate the pressure. double gasVolume = 0.0; double liquidVolume = 0.0; PhysTools.normalizeFluidMixture(ref currentFluidTypeMap); //Make sure that the percentages are normalized, otherwise very bad things would happen foreach (KeyValuePair<FluidType, double> kvp in currentFluidTypeMap) { //NOTE: If we have multiple gasses that need to compress differently (I don't think that is possible, even with AIR and STEAM), then we need to re-think this algorithm from the ground up. if (kvp.Key.isGas) gasVolume += kvp.Value * currentVolume; else liquidVolume += kvp.Value * currentVolume; } percentFilled = liquidVolume / capacity; double volumeForGas = capacity - liquidVolume; tankPressure = (gasVolume / volumeForGas) - 1.0; //Subtract 1.0 to convert from bara to barg. } else { double adjustmentToMake = 0.0; //Vent any gasses out the top. foreach(FluidType key in currentFluidTypeMap.Keys.ToList<FluidType>()) { if(key.isGas) { adjustmentToMake += currentFluidTypeMap[key]; currentFluidTypeMap.Remove(key); } } if (adjustmentToMake > 0.0) { //We ended up removing some gas, so we need to re-normalize, and adjust the values PhysTools.normalizeFluidMixture(ref currentFluidTypeMap); volumeToAdd *= (1.0 - adjustmentToMake); //Remove the volume of gas that is escaping } tankPressure = 0.4; //TODO: Adjust non-sealed tank outlet pressures based on size/shape, etc. currentVolume += volumeToAdd; percentFilled = currentVolume / capacity; } } inletTemperature = currentTemperature; outletTemperature = currentTemperature; }
public void applySourceResponse(SettingResponseData sourceResponse) { this.fluidTypeMap = sourceResponse.fluidTypeMap; this.temperature = sourceResponse.temperature; }
private SettingResponseData setFlowValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, FlowComponent[] nodes, bool isDeliverySide, bool lastTime) { if(isDeliverySide) { for (int i = 0; i < nodes.Length; i++) { nodes[i].setDeliveryValues(baseData, this, flowPercentageSolutions[baseData.flowDriver.name][i] * flowVolume, lastTime); } finalFlow = flowVolume; currentFluidTypeMap = baseData.fluidTypeMap; //On the delivery side, the mixture comes from passed in arguments inletTemperature = baseData.temperature; outletTemperature = baseData.temperature; return null; } else { SettingResponseData[] responses = new SettingResponseData[nodes.Length]; double[] volumes = new double[nodes.Length]; bool hasNull = false; for (int attempt = 0; attempt < 2; attempt++) { hasNull = false; for (int i = 0; i < nodes.Length; i++) { volumes[i] = flowPercentageSolutions[baseData.flowDriver.name][i] * flowVolume; if(responses[i] == null) responses[i] = nodes[i].setSourceValues(baseData, this, volumes[i], lastTime); if (responses[i] == null) hasNull = true; } if (!hasNull) break; } if (hasNull) return null; finalFlow = flowVolume; SettingResponseData ret = PhysTools.mixFluidPercentsAndTemperatures(responses, volumes); ret.flowVolume = flowVolume; //ret.fluidTypeMap = PhysTools.mixFluids(responses, volumes); currentFluidTypeMap = ret.fluidTypeMap; //On source side, the mixture comes from the return values inletTemperature = ret.temperature; outletTemperature = ret.temperature; return ret; } }
private SettingResponseData setCombiningFlowValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, FlowComponent[] nodes, bool isDeliverySide, bool lastTime) { int index = indexByName[caller.name]; setCombiningVolumeMap[index] = flowVolume; double volumeSum = 0.0; for (int i = 0; i < setCombiningVolumeMap.Length; i++) { if (setCombiningVolumeMap[i] < 0.0) return null; //We haven't seen all of the inputs to combine them... else volumeSum += setCombiningVolumeMap[i]; } finalFlow = volumeSum; if (isDeliverySide) { for (int i = 0; i < nodes.Length; i++) { nodes[i].setDeliveryValues(baseData, this, volumeSum, lastTime); } currentFluidTypeMap = baseData.fluidTypeMap; //On the delivery side, the mixture comes from passed in arguments inletTemperature = baseData.temperature; outletTemperature = baseData.temperature; return null; } else { if (nodes.Length != 1) throw new Exception("Source combiners can only have 1 node"); if (setterDownstreamValue == null) setterDownstreamValue = nodes[0].setSourceValues(baseData, this, volumeSum, lastTime); SettingResponseData ret = new SettingResponseData(); ret.flowVolume = volumeSum; ret.fluidTypeMap = setterDownstreamValue.fluidTypeMap; ret.temperature = setterDownstreamValue.temperature; currentFluidTypeMap = ret.fluidTypeMap; //On source side, the mixture comes from the return values inletTemperature = ret.temperature; outletTemperature = ret.temperature; return ret; } }
public override void resetState() { base.resetState(); for (int i = 0; i < setCombiningVolumeMap.Length; i++) { setCombiningVolumeMap[i] = -1.0; } combinerDownstreamValues.Clear(); foreach (KeyValuePair<String, double[]> iter in combinerMap) { for (int i = 0; i < iter.Value.Length; i++) { if (!indexesUsedByPump.ContainsKey(iter.Key) || indexesUsedByPump[iter.Key][i]) iter.Value[i] = -1.0; //Initialize with all negative numbers, and wait until they are not negative to know when we are done. else iter.Value[i] = 0.0; //Initialize to 0 if this pump will never get this number } } setterDownstreamValue = null; }