public override FlowResponseData getFlowDriverSourcePossibleValues(FlowCalculationData baseData, FlowDriverModifier modifier)
 {
     pumpingPercent = 1.0;
     FlowResponseData normalResponse = base.getFlowDriverSourcePossibleValues(baseData, modifier);
     lastSourcePossibleValue = normalResponse;
     return normalResponse;
 }
Пример #2
0
        public FlowResponseData clone()
        {
            FlowResponseData ret = new FlowResponseData();

            ret.flowPercent = flowPercent;
            ret.flowVolume = flowVolume;
            ret.backPressure = backPressure;

            ret.fluidTypeMap = PhysTools.DictionaryCloner<FluidType, double>.cloneDictionary(fluidTypeMap);

            return ret;
        }
Пример #3
0
        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;
        }
Пример #4
0
        public bool updateStateRequiresNewSolution(FlowResponseData sourceAbility, FlowResponseData deliveryAbility)
        {
            bool needsNewSolution = false;
            this.sourceAbility = sourceAbility;
            this.deliveryAbility = deliveryAbility;
            double minFlowAbility = Math.Min(sourceAbility.flowPercent, deliveryAbility.flowPercent);
            if (minFlowAbility < flowPercent)
            {
                flowPercent = minFlowAbility;
                needsNewSolution = true;
            }

            if (sourceAbility.flowPercent < minSourceFlowPercent)
                minSourceFlowPercent = sourceAbility.flowPercent;
            if (deliveryAbility.flowPercent < minDeliveryFlowPercent)
                minDeliveryFlowPercent = deliveryAbility.flowPercent;

            return needsNewSolution;
        }
Пример #5
0
 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;
 }
Пример #6
0
        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);
        }
Пример #7
0
        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;
        }
 public override void resetState()
 {
     base.resetState();
     lastSourcePossibleValue = null;
 }