コード例 #1
0
 public override FlowResponseData getFlowDriverSourcePossibleValues(FlowCalculationData baseData, FlowDriverModifier modifier)
 {
     pumpingPercent = 1.0;
     FlowResponseData normalResponse = base.getFlowDriverSourcePossibleValues(baseData, modifier);
     lastSourcePossibleValue = normalResponse;
     return normalResponse;
 }
コード例 #2
0
        public override FlowResponseData getFlowDriverDeliveryPossibleValues(FlowCalculationData baseData, FlowDriverModifier modifier)
        {
            pumpingPercent = lastSourcePossibleValue.flowPercent;
            mcrPressure = lastSourcePossibleValue.backPressure;
            FlowResponseData normalResponse = base.getFlowDriverDeliveryPossibleValues(baseData, modifier);

            double deltaP = lastSourcePossibleValue.backPressure - normalResponse.backPressure;
            if (deltaP < minDeltaP)
            {
                normalResponse.flowPercent = 0.0;
            }
            else
            {
                double flowPercent = 1.0;                   //Default to 1, in case deltaP > maxDeltaP, in which case, we do 100% of what we can.
                if (deltaP < maxDeltaP)
                {
                    flowPercent = (deltaP - minDeltaP) / (maxDeltaP - minDeltaP);
                }

                normalResponse.flowPercent = Math.Min(normalResponse.flowPercent, lastSourcePossibleValue.flowPercent) * flowPercent;
            }
            normalResponse.flowVolume = baseData.desiredFlowVolume * normalResponse.flowPercent;

            return normalResponse;
        }
コード例 #3
0
ファイル: FlowLine.cs プロジェクト: appritech/appriphys
 public override FlowResponseData getSourcePossibleValues(FlowCalculationData baseData, FlowComponent caller, double flowPercent, double pressurePercent)
 {
     double limitedFlowPercent = getLimitedFlowPercent(baseData, caller, flowPercent);
     double limitedPressurePercent = getLimitedPressurePercent(baseData, caller, flowPercent, pressurePercent);
     FlowResponseData ret = sourceComponent.getSourcePossibleValues(baseData, this, limitedFlowPercent, limitedPressurePercent);
     if (ret != null)
     {
         setPressuresForSourceSide(baseData.pressure, ret.backPressure, limitedPressurePercent, pressurePercent);
     }
     return ret;
 }
コード例 #4
0
ファイル: GraphSolver.cs プロジェクト: appritech/appriphys
 public void connectComponents()
 {
     foreach(FlowComponent iter in components.Values)
     {
         iter.connectSelf(components);
     }
     foreach(FlowDriver iter in flowDrivers.Values)
     {
         FlowCalculationData baseData = new FlowCalculationData(iter, angerMap, 0);
         baseData.flowDriver = iter;
         iter.exploreDeliveryGraph(baseData, null);
         iter.exploreSourceGraph(baseData, null);
         flowDriverModifiers[iter.name] = new FlowDriverModifier();
     }
 }
コード例 #5
0
ファイル: FlowDriver.cs プロジェクト: appritech/appriphys
        public bool applySolution(FlowCalculationData baseData, FlowDriverModifier modifier, bool lastTime)
        {
            if (solutionApplied)
                return true;                     //If we have already successfully sent all our data, then we shouldn't do it again...

            SettingResponseData sourceResponse = setSourceValues(baseData, null, pumpingPercent * mcrRating * modifier.flowPercent, lastTime);
            if (sourceResponse != null)
            {
                baseData.applySourceResponse(sourceResponse);
                setDeliveryValues(baseData, null, pumpingPercent * mcrRating * modifier.flowPercent, lastTime);
                solutionApplied = true;
            }

            return solutionApplied;
        }
コード例 #6
0
ファイル: FlowDriver.cs プロジェクト: appritech/appriphys
 public override FlowResponseData getDeliveryPossibleValues(FlowCalculationData baseData, FlowComponent caller, double flowPercent, double pressurePercent)
 {
     if (caller == null)
     {
         //This shouldn't happen anymore, since GraphSolver calls the pump-specific (i.e. not override) version.
         baseData.flowDriver = this;
         baseData.desiredFlowVolume = pumpingPercent * mcrRating * flowPercent;
         baseData.pressure = mcrPressure * pressurePercent;
         outletPressure = baseData.pressure;
         return deliveryComponent.getDeliveryPossibleValues(baseData, this, 1.0, 1.0);             //Always ask 100% of whatever desired flow we have
     }
     else
     {
         return null;                //TODO: Handle this case when pumps are in series
     }
 }
コード例 #7
0
ファイル: Tank.cs プロジェクト: appritech/appriphys
        public override FlowResponseData getDeliveryPossibleValues(FlowCalculationData baseData, FlowComponent caller, double flowPercent, double pressurePercent)
        {
            FlowResponseData ret = new FlowResponseData();

            ret.backPressure = tankPressure;

            if (isSealed)
            {
                double deltaPressure = baseData.pressure - tankPressure;
                if(deltaPressure < 0.0)
                {
                    //There is too much back-pressure for this pump to overcome it. Thus, nothing will flow in.
                    ret.flowPercent = 0.0;
                }
                else if(deltaPressure > normalPressureDelta || normalPressureDelta == 0.0)          //Don't allow else to divide by 0
                {
                    //We don't add any restriction, since the dP is greater than our defined 'normal'.
                    ret.flowPercent = flowPercent;
                }
                else
                {
                    //Here we need to do a linear interpolation between deltaPressure = normalPressure meaning 1, and deltaPressure = 0 meaning 0.
                    //Thus, at normalPressure, we get full flow, and at no pressure difference, we get no flow.
                    ret.flowPercent = deltaPressure / normalPressureDelta * flowPercent;
                }
            }
            else
            {
                if (currentVolume < double.MaxValue)             //TODO: Make it so that tanks can't overflow, especially sealed tanks... Right now, it will pretty much always accept any flow that we want to put into it...
                {
                    ret.flowPercent = flowPercent;           //Allow everything that they are asking for, since we don't do restrictions inside the tank.
                }
                else
                {
                    ret.flowPercent = 0.0;
                }
            }

            ret.flowVolume = flowPercent * baseData.desiredFlowVolume;
            ret.fluidTypeMap = currentFluidTypeMap;
            outletPressure = ret.backPressure;
            return ret;
        }
コード例 #8
0
ファイル: FlowLine.cs プロジェクト: appritech/appriphys
        private double getLimitedPressurePercent(FlowCalculationData baseData, FlowComponent caller, double flowPercent, double pressurePercent)
        {
            double limitedPressurePercent = pressurePercent * normalPressureDropPercent;

            if(flowPercent == 0.0)
            {
                limitedPressurePercent = 0.0;
            }
            else if(flowAllowedPercent < flowPercent)
            {
                //limitedPressurePercent *= flowAllowedPercent / flowPercent;                   //If flowPercent is included, then splitters with different maxes don't work well...
                limitedPressurePercent *= flowAllowedPercent;
            }

            return limitedPressurePercent;
        }
コード例 #9
0
ファイル: FlowLine.cs プロジェクト: appritech/appriphys
 public override void exploreDeliveryGraph(FlowCalculationData baseData, FlowComponent caller)
 {
     deliveryComponent.exploreDeliveryGraph(baseData, this);
 }
コード例 #10
0
ファイル: FlowComponent.cs プロジェクト: appritech/appriphys
 public abstract SettingResponseData setSourceValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, bool lastTime);
コード例 #11
0
ファイル: FlowLine.cs プロジェクト: appritech/appriphys
        private double getLimitedFlowPercent(FlowCalculationData baseData, FlowComponent caller, double flowPercent)
        {
            double limitedFlowPercent = Math.Min(flowPercent, flowAllowedPercent);
            if (baseData.desiredFlowVolume * limitedFlowPercent > maxFlow)
            {
                //Need to cut down even further, so that we don't go over our maximum.
                limitedFlowPercent = maxFlow / baseData.desiredFlowVolume;
            }

            //Apply anger effects, if they are needed.
            if (baseData.angerMap.ContainsKey(name))
            {
                limitedFlowPercent *= baseData.angerMap[name];
            }

            return limitedFlowPercent;
        }
コード例 #12
0
ファイル: Tank.cs プロジェクト: appritech/appriphys
        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;
        }
コード例 #13
0
ファイル: Tank.cs プロジェクト: appritech/appriphys
 public override void exploreSourceGraph(FlowCalculationData baseData, FlowComponent caller)
 {
     //Don't have to do anything, since this is the end of the line
 }
コード例 #14
0
ファイル: Junction.cs プロジェクト: appritech/appriphys
        private double[] modifyPreferenceBasedOnBackPressures(double[] preferredFlowPercent, FlowResponseData[] responses, FlowCalculationData baseData)
        {
            if (baseData.pressure == 0.0)
                return preferredFlowPercent;                //We don't want to have a divide by zero down below.

            //1.0 - backpressure/mcr-pressure seems to be a good starting guess for a scaler.
            double sumBeforeModification = 0.0;
            for(int i = 0; i < preferredFlowPercent.Length; i++)
            {
                sumBeforeModification += preferredFlowPercent[i];
                double modifier = Math.Max(1.0 - (responses[i].backPressure / baseData.pressure), 0.000001);            //Don't let the number go completely to zero.
                preferredFlowPercent[i] *= modifier;
            }
            return PhysTools.normalizePercentArray(preferredFlowPercent, sumBeforeModification);
        }
コード例 #15
0
ファイル: FlowLine.cs プロジェクト: appritech/appriphys
 public override void setDeliveryValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, bool lastTime)
 {
     finalFlow = flowVolume;
     deliveryComponent.setDeliveryValues(baseData, this, flowVolume, lastTime);
     currentFluidTypeMap = baseData.fluidTypeMap;               //On the delivery side, the mixture comes from passed in arguments
     inletTemperature = baseData.temperature;
     outletTemperature = baseData.temperature;
 }
コード例 #16
0
ファイル: Junction.cs プロジェクト: appritech/appriphys
        private FlowResponseData calculateCombiningFunctionality(FlowCalculationData baseData, FlowComponent caller, double flowPercent, FlowComponent[] nodes, bool isDeliverySide, double pressurePercent)
        {
            if (!combinerMap.ContainsKey(baseData.flowDriver.name))
            {
                double[] toAdd = new double[indexByName.Count];
                for (int i = 0; i < indexByName.Count; i++)
                {
                    if (!indexesUsedByPump.ContainsKey(baseData.flowDriver.name) || indexesUsedByPump[baseData.flowDriver.name][i])
                        toAdd[i] = -1.0;                            //Initialize with all negative numbers, and wait until they are not negative to know when we are done.
                    else
                        toAdd[i] = 0.0;                             //Initialize to 0 if this pump will never get this number
                }
                combinerMap[baseData.flowDriver.name] = toAdd;
            }

            double[] percentMap = combinerMap[baseData.flowDriver.name];
            int index = indexByName[caller.name];
            percentMap[index] = flowPercent;

            double percentSum = 0.0;
            for (int i = 0; i < percentMap.Length; i++)
            {
                if (percentMap[i] < 0.0)
                    return null;                //We haven't seen all of the inputs to combine them... thus, return null until we do see them all.
                else
                    percentSum += percentMap[i];
            }

            if (percentSum > 1.0)
                percentSum = 1.0;

            if (!combinerDownstreamValues.ContainsKey(baseData.flowDriver.name))
            {
                if (isDeliverySide)
                    combinerDownstreamValues[baseData.flowDriver.name] = deliveryComponents[0].getDeliveryPossibleValues(baseData, this, percentSum, pressurePercent);
                else
                    combinerDownstreamValues[baseData.flowDriver.name] = sourceComponents[0].getSourcePossibleValues(baseData, this, percentSum, pressurePercent);
            }

            FlowResponseData ret = combinerDownstreamValues[baseData.flowDriver.name].clone();
            lastCombinePercent = ret.flowPercent;

            if (percentSum != 0.0)
            {
                ret.flowPercent *= (percentMap[index] / percentSum);             //The divide here is to normalize it.
                ret.flowVolume *= (percentMap[index] / percentSum);
            }

            if (!flowPercentageSolutions.ContainsKey(baseData.flowDriver.name))
                flowPercentageSolutions[baseData.flowDriver.name] = new double[1];
            flowPercentageSolutions[baseData.flowDriver.name][0] = ret.flowPercent;

            setPressures(baseData.pressure, ret.backPressure, pressurePercent, isDeliverySide);

            return ret;
        }
コード例 #17
0
ファイル: Junction.cs プロジェクト: appritech/appriphys
        private FlowResponseData calculateSplittingFunctionality(FlowCalculationData baseData, double flowPercent, FlowComponent[] nodes, bool isDeliverySide, double pressurePercent)
        {
            FlowResponseData[] responses = new FlowResponseData[nodes.Length];
            bool foundNull = false;
            double maxBackPressure = 0.0;
            for (int attempt = 0; attempt < 2; attempt++)
            {
                //Most of the time, we will need to ask twice, because some will be null the first time.
                foundNull = false;
                for (int i = 0; i < nodes.Length; i++)
                {
                    if (responses[i] == null)
                    {
                        if (isDeliverySide)
                            responses[i] = nodes[i].getDeliveryPossibleValues(baseData, this, Math.Min(flowPercent, maxWeights[i]), pressurePercent);
                        else
                            responses[i] = nodes[i].getSourcePossibleValues(baseData, this, Math.Min(flowPercent, maxWeights[i]), pressurePercent);
                    }

                    if (responses[i] == null)
                        foundNull = true;
                    else if (responses[i].backPressure > maxBackPressure)
                        maxBackPressure = responses[i].backPressure;
                }

                if (!foundNull)
                    break;
            }
            if (foundNull)
            {
                return null;                //We weren't able to get everything, and this is probably because there is another splitter up stream that will retry us again.
            }

            if (!flowPercentageSolutions.ContainsKey(baseData.flowDriver.name))
                flowPercentageSolutions[baseData.flowDriver.name] = new double[nodes.Length];

            //If we get here, then we have all the info we should need to solve ourselves.

            double desiredPercent = flowPercent;

            double[] maxFlowPercent = new double[nodes.Length];
            double[] preferredFlowPercent = new double[nodes.Length];
            double percentToReturn = 0.0;
            double sumOfMaxFlow = 0;
            double currentSum = 0.0;

            if (linkedCombiner != null)
            {
                desiredPercent = Math.Min(linkedCombiner.lastCombinePercent, flowPercent);            //All are equal... grab first. This is the combiner's maxFlow

                double[] flowPercentToCombiner;
                //NOTE: Both solutions with both divisors gave the same answer, and I found the bug elsewhere...
                //TODO: Determing what divisor we actually want to use.
                if (linkedCombiner.combinerMap.ContainsKey(baseData.flowDriver.name))
                    flowPercentToCombiner = linkedCombiner.combinerMap[baseData.flowDriver.name];
                else
                {
                    flowPercentToCombiner = new double[nodes.Length];
                    for (int i = 0; i < nodes.Length; i++)
                        flowPercentToCombiner[i] = responses[i].flowPercent;              //This was my original solution, but the map is better.
                }

                double tempSum = 0.0;
                for (int i = 0; i < nodes.Length; i++)
                {
                    maxFlowPercent[i] = Math.Min(maxWeights[i], flowPercentToCombiner[i]);
                    preferredFlowPercent[i] = Math.Min(normalWeights[i], maxFlowPercent[i]) * desiredPercent;
                    tempSum += preferredFlowPercent[i];
                }

                bool modifySplitBasedOnBackPressures = true;            //I can foresee this wanting to be an optional parameter, sometimes doing it, and sometimes not.
                if (modifySplitBasedOnBackPressures)
                {
                    preferredFlowPercent = modifyPreferenceBasedOnBackPressures(preferredFlowPercent, responses, baseData);
                }

                preferredFlowPercent = fixPercents(preferredFlowPercent, maxFlowPercent, desiredPercent);
                //Normalize preferredFlowPercent (since we know the final flow as desiredPercent, we can safely do so in this case)
                for (int i = 0; i < nodes.Length; i++)
                {
                    currentSum += preferredFlowPercent[i];
                    percentToReturn += preferredFlowPercent[i];
                    sumOfMaxFlow += maxFlowPercent[i];
                }
            }
            else
            {
                desiredPercent = flowPercent;

                for (int i = 0; i < nodes.Length; i++)
                {
                    maxFlowPercent[i] = Math.Min(maxWeights[i], responses[i].flowPercent);
                    preferredFlowPercent[i] = Math.Min(normalWeights[i], maxFlowPercent[i]) * desiredPercent;
                    currentSum += preferredFlowPercent[i];
                    percentToReturn += preferredFlowPercent[i];
                    sumOfMaxFlow += maxFlowPercent[i];
                }
            }

            //TODO: Find better way to handle this. The 0.000000001 is there to handle rounding errors, when the sum really is the same number, but it rounds to slightly less...
            if (currentSum < desiredPercent - 0.000000001 && sumOfMaxFlow > 0.0)                //sum > 0.0 helps us avoid a divide by 0 below. Also, if we can't push anything, then 0 is the right answer
            {
                percentToReturn = 0;
                for (int i = 0; i < nodes.Length; i++)
                {
                    double trueFlowPercent;
                    if (sumOfMaxFlow == 0.0)
                        trueFlowPercent = 0.0;
                    else
                        trueFlowPercent = desiredPercent * (maxFlowPercent[i] / sumOfMaxFlow);

                    trueFlowPercent = Math.Min(trueFlowPercent, maxWeights[i]);            //Probably don't need this one, since the one right below is better.
                    trueFlowPercent = Math.Min(trueFlowPercent, maxFlowPercent[i]);
                    flowPercentageSolutions[baseData.flowDriver.name][i] = trueFlowPercent;
                    percentToReturn += trueFlowPercent;
                }
            }
            else
            {
                for (int i = 0; i < nodes.Length; i++)
                {
                    double trueFlowPercent = preferredFlowPercent[i];           //It all works out with preferred values.
                    flowPercentageSolutions[baseData.flowDriver.name][i] = trueFlowPercent;
                }
            }

            //Need to normalize the flowPercenageSolutions, so that they sum to 1.0, so that when we set values, we are spliting 100 % of the smaller portion that is coming down to us(and don't double-limit things).
            if (percentToReturn != 0.0)
            {
                for (int i = 0; i < nodes.Length; i++)
                    flowPercentageSolutions[baseData.flowDriver.name][i] /= percentToReturn;
            }

            FlowResponseData ret = new FlowResponseData();
            ret.flowPercent = percentToReturn;
            ret.flowVolume = percentToReturn * baseData.desiredFlowVolume;
            ret.backPressure = maxBackPressure;
            setPressures(baseData.pressure, ret.backPressure, pressurePercent, isDeliverySide);

            return ret;
        }
コード例 #18
0
ファイル: Junction.cs プロジェクト: appritech/appriphys
 public override SettingResponseData setSourceValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, bool lastTime)
 {
     if (!hasMultipleDeliveryComponents)
         return setFlowValues(baseData, caller, flowVolume, sourceComponents, false, lastTime);
     else
         return setCombiningFlowValues(baseData, caller, flowVolume, sourceComponents, false, lastTime);
 }
コード例 #19
0
ファイル: Junction.cs プロジェクト: appritech/appriphys
 public override void setDeliveryValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, bool lastTime)
 {
     if (hasMultipleDeliveryComponents)
         setFlowValues(baseData, caller, flowVolume, deliveryComponents, true, lastTime);
     else
         setCombiningFlowValues(baseData, caller, flowVolume, deliveryComponents, true, lastTime);
 }
コード例 #20
0
ファイル: Junction.cs プロジェクト: appritech/appriphys
 public override FlowResponseData getSourcePossibleValues(FlowCalculationData baseData, FlowComponent caller, double flowPercent, double pressurePercent)
 {
     if (!hasMultipleDeliveryComponents)
         return calculateSplittingFunctionality(baseData, flowPercent, sourceComponents, false, pressurePercent);
     else
         return calculateCombiningFunctionality(baseData, caller, flowPercent, deliveryComponents, false, pressurePercent);
 }
コード例 #21
0
ファイル: FlowLine.cs プロジェクト: appritech/appriphys
 public override void exploreSourceGraph(FlowCalculationData baseData, FlowComponent caller)
 {
     sourceComponent.exploreSourceGraph(baseData, this);
 }
コード例 #22
0
ファイル: FlowComponent.cs プロジェクト: appritech/appriphys
 public abstract void setDeliveryValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, bool lastTime);
コード例 #23
0
ファイル: FlowComponent.cs プロジェクト: appritech/appriphys
 public abstract FlowResponseData getSourcePossibleValues(FlowCalculationData baseData, FlowComponent caller, double flowPercent,double pressurePercent);
コード例 #24
0
ファイル: Junction.cs プロジェクト: appritech/appriphys
        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;
            }
        }
コード例 #25
0
ファイル: Tank.cs プロジェクト: appritech/appriphys
 public override FlowResponseData getSourcePossibleValues(FlowCalculationData baseData, FlowComponent caller, double flowPercent, double pressurePercent)
 {
     FlowResponseData ret = new FlowResponseData();
     if(currentVolume > 0.0)
     {
         ret.flowPercent = flowPercent;           //Allow everything that they are asking for, since we don't do restrictions inside the tank.
     }
     else
     {
         ret.flowPercent = 0.0f;
     }
     ret.flowVolume = flowPercent * baseData.desiredFlowVolume;
     ret.backPressure = tankPressure;
     ret.fluidTypeMap = currentFluidTypeMap;
     outletPressure = ret.backPressure;
     return ret;
 }
コード例 #26
0
ファイル: Junction.cs プロジェクト: appritech/appriphys
 public override void exploreDeliveryGraph(FlowCalculationData baseData, FlowComponent caller)
 {
     for (int i = 0; i < deliveryComponents.Length; i++)
     {
         deliveryComponents[i].exploreDeliveryGraph(baseData, this);
     }
     if (!hasMultipleDeliveryComponents)           //Do the following if we are combining, so we know which combining imputs actually apply to given pump
     {
         if (!indexesUsedByPump.ContainsKey(baseData.flowDriver.name))
             indexesUsedByPump[baseData.flowDriver.name] = new bool[sourceComponents.Length];
         indexesUsedByPump[baseData.flowDriver.name][indexByName[caller.name]] = true;
     }
 }
コード例 #27
0
ファイル: Tank.cs プロジェクト: appritech/appriphys
        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;
        }
コード例 #28
0
ファイル: FlowLine.cs プロジェクト: appritech/appriphys
 public override SettingResponseData setSourceValues(FlowCalculationData baseData, FlowComponent caller, double flowVolume, bool lastTime)
 {
     finalFlow = flowVolume;
     SettingResponseData ret = sourceComponent.setSourceValues(baseData, this, flowVolume, lastTime);
     if (ret != null)
     {
         currentFluidTypeMap = ret.fluidTypeMap;                    //On source side, the mixture comes from the return values
         inletTemperature = ret.temperature;
         outletTemperature = ret.temperature;
     }
     return ret;
 }
コード例 #29
0
ファイル: Junction.cs プロジェクト: appritech/appriphys
        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;
            }
        }
コード例 #30
0
ファイル: GraphSolver.cs プロジェクト: appritech/appriphys
        private bool attemptSolve(FlowDriver p, int attempt)
        {
            double flowModifier = flowDriverModifiers[p.name].flowPercent;

            FlowCalculationData baseData = new FlowCalculationData(p, angerMap, attempt);
            FlowResponseData sourceAbility = p.getFlowDriverSourcePossibleValues(baseData, flowDriverModifiers[p.name]);
            baseData.fluidTypeMap = sourceAbility.fluidTypeMap;             //Pass the mixture stuff from source to delivery
            FlowResponseData deliveryAbility = p.getFlowDriverDeliveryPossibleValues(baseData, flowDriverModifiers[p.name]);

            if (flowDriverModifiers[p.name].updateStateRequiresNewSolution(sourceAbility, deliveryAbility))
                return false;

            return true;
        }