Example #1
0
        public SimulationManager()
        {
            Stages = new Stage[0];
            LastStage = new Stage();

            Gravity = 9.81d;
            Atmosphere = 0d;
        }
Example #2
0
        private void DrawTWR(Stage[] stages)
        {
            GUILayout.BeginVertical(GUILayout.Width(90));
            GUILayout.Label("TWR (Max)", headingStyle);

            for (int i = 0; i < stages.Length; i++)
            {
                if (!settings.Get<bool>("_SAVEONCHANGE_SHOW_ALL_STAGES") && stages[i].deltaV == 0)
                {
                    continue;
                }

                GUILayout.Label(EngineerTools.SimpleFormatter(stages[i].thrustToWeight, "", 2) + " (" + EngineerTools.SimpleFormatter(stages[i].maxThrustToWeight, "", 2) + ")", dataStyle);
            }

            GUILayout.EndVertical();
        }
Example #3
0
        private void DrawTime(Stage[] stages)
        {
            GUILayout.BeginVertical(GUILayout.Width(60));
            GUILayout.Label("TIME", headingStyle);

            for (int i = 0; i < stages.Length; i++)
            {
                if (!settings.Get<bool>("_SAVEONCHANGE_SHOW_ALL_STAGES") && stages[i].deltaV == 0)
                {
                    continue;
                }
                GUILayout.Label(Tools.FormatTime(stages[i].time), dataStyle);
            }

            GUILayout.EndVertical();
        }
Example #4
0
        private void DrawThrust(Stage[] stages)
        {
            GUILayout.BeginVertical(GUILayout.Width(85));
            GUILayout.Label("THRUST", headingStyle);

            for (int i = 0; i < stages.Length; i++)
            {
                if (!settings.Get<bool>("_SAVEONCHANGE_SHOW_ALL_STAGES") && stages[i].deltaV == 0)
                {
                    continue;
                }
                GUILayout.Label(EngineerTools.ForceFormatter(stages[i].thrust), dataStyle);
            }

            GUILayout.EndVertical();
        }
Example #5
0
        private void DrawStage(Stage[] stages)
        {
            GUILayout.BeginVertical();
            GUILayout.Label("");

            for (int i = 0; i < stages.Length; i++)
            {
                if (!settings.Get<bool>("_SAVEONCHANGE_SHOW_ALL_STAGES") && stages[i].deltaV == 0)
                {
                    continue;
                }
                GUILayout.Label("S " + i, headingStyle);
            }

            GUILayout.EndVertical();
        }
Example #6
0
        private void DrawMass(Stage[] stages)
        {
            GUILayout.BeginVertical(GUILayout.Width(150));
            GUILayout.Label("MASS", headingStyle);

            for (int i = 0; i < stages.Length; i++)
            {
                if (!settings.Get<bool>("_SAVEONCHANGE_SHOW_ALL_STAGES") && stages[i].deltaV == 0)
                {
                    continue;
                }
                GUILayout.Label(EngineerTools.WeightFormatter(stages[i].mass, stages[i].totalMass), dataStyle);
            }

            GUILayout.EndVertical();
        }
Example #7
0
        private void DrawIsp(Stage[] stages)
        {
            GUILayout.BeginVertical(GUILayout.Width(50));
            GUILayout.Label("ISP", headingStyle);

            for (int i = 0; i < stages.Length; i++)
            {
                if (!settings.Get<bool>("_SAVEONCHANGE_SHOW_ALL_STAGES") && stages[i].deltaV == 0)
                {
                    continue;
                }
                GUILayout.Label(EngineerTools.SimpleFormatter(stages[i].isp, "s"), dataStyle);
            }

            GUILayout.EndVertical();
        }
Example #8
0
        private void DrawDeltaV(Stage[] stages)
        {
            GUILayout.BeginVertical(GUILayout.Width(115));
            GUILayout.Label("DELTA-V", headingStyle);

            for (int i = 0; i < stages.Length; i++)
            {
                if (!settings.Get<bool>("_SAVEONCHANGE_SHOW_ALL_STAGES") && stages[i].deltaV == 0)
                {
                    continue;
                }
                GUILayout.Label(EngineerTools.SimpleFormatter(stages[i].deltaV, stages[i].inverseTotalDeltaV, "m/s"), dataStyle);
            }

            GUILayout.EndVertical();
        }
Example #9
0
        // This function runs the simulation and returns a newly created array of Stage objects
        public Stage[] RunSimulation()
        {
            if (SimManager.logOutput)
                MonoBehaviour.print("RunSimulation started");
            _timer.Start();
            // Start with the last stage to simulate
            // (this is in a member variable so it can be accessed by AllowedToStage and ActivateStage)
            currentStage = lastStage;

            LogMsg log = null;
            if (SimManager.logOutput)
                log = new LogMsg();

            // Work out which engines would be active if just doing the staging and if this is different to the
            // currently active engines then generate an extra stage
            // Loop through all the engines
            foreach (EngineSim engine in allEngines)
            {
                if (log != null)
                    log.buf.AppendLine("Testing engine mod of " + engine.partSim.name + ":" + engine.partSim.partId);
                bool bActive = engine.isActive;
                bool bStage = (engine.partSim.inverseStage >= currentStage);
                if (log != null)
                    log.buf.AppendLine("bActive = " + bActive + "   bStage = " + bStage);
                if (HighLogic.LoadedSceneIsFlight)
                {
                    if (bActive != bStage)
                    {
                        // If the active state is different to the state due to staging
                        if (log != null)
                            log.buf.AppendLine("Need to do current active engines first");

                        doingCurrent = true;
                        currentStage++;
                        break;
                    }
                }
                else
                {
                    if (bStage)
                    {
                        if (log != null)
                            log.buf.AppendLine("Marking as active");

                        engine.isActive = true;
                    }
                }
            }

            if (log != null)
                log.Flush();

            // Create the array of stages that will be returned
            Stage[] stages = new Stage[currentStage + 1];

            // Loop through the stages
            while (currentStage >= 0)
            {
                if (log != null)
                {
                    log.buf.AppendLine("Simulating stage " + currentStage);
                    log.buf.AppendLine("ShipMass = " + ShipMass);
                    log.Flush();
                    _timer.Reset();
                    _timer.Start();
                }

                // Update active engines and resource drains
                UpdateResourceDrains();

                // Create the Stage object for this stage
                Stage stage = new Stage();

                stageTime = 0d;
                vecStageDeltaV = Vector3.zero;
                stageStartMass = ShipMass;
                stepStartMass = stageStartMass;
                stepEndMass = 0;

                CalculateThrustAndISP();

                // Store various things in the Stage object
                stage.thrust = totalStageThrust;
                //MonoBehaviour.print("stage.thrust = " + stage.thrust);
                stage.thrustToWeight = totalStageThrust / (stageStartMass * gravity);
                stage.maxThrustToWeight = stage.thrustToWeight;
                //MonoBehaviour.print("StageMass = " + stageStartMass);
                //MonoBehaviour.print("Initial maxTWR = " + stage.maxThrustToWeight);
                stage.actualThrust = totalStageActualThrust;
                stage.actualThrustToWeight = totalStageActualThrust / (stageStartMass * gravity);

                // Calculate the cost and mass of this stage
                foreach (PartSim partSim in allParts)
                {
                    if (partSim.decoupledInStage == currentStage - 1)
                    {
                        stage.cost += partSim.cost;
                        stage.mass += partSim.GetStartMass();
                    }
                }

                if (log != null)
                    MonoBehaviour.print("Stage setup took " + _timer.ElapsedMilliseconds + "ms");

                // Now we will loop until we are allowed to stage
                int loopCounter = 0;
                while (!AllowedToStage())
                {
                    loopCounter++;
                    //MonoBehaviour.print("loop = " + loopCounter);

                    // Calculate how long each draining tank will take to drain and run for the minimum time
                    double resourceDrainTime = double.MaxValue;
                    PartSim partMinDrain = null;
                    foreach (PartSim partSim in drainingParts)
                    {
                        double time = partSim.TimeToDrainResource();
                        if (time < resourceDrainTime)
                        {
                            resourceDrainTime = time;
                            partMinDrain = partSim;
                        }
                    }

                    if (log != null)
                        MonoBehaviour.print("Drain time = " + resourceDrainTime + " (" + partMinDrain.name + ":" + partMinDrain.partId + ")");

                    foreach (PartSim partSim in drainingParts)
                        partSim.DrainResources(resourceDrainTime);

                    // Get the mass after draining
                    stepEndMass = ShipMass;
                    stageTime += resourceDrainTime;

                    double stepEndTWR = totalStageThrust / (stepEndMass * gravity);
                    //MonoBehaviour.print("After drain mass = " + stepEndMass);
                    //MonoBehaviour.print("currentThrust = " + totalStageThrust);
                    //MonoBehaviour.print("currentTWR = " + stepEndTWR);
                    if (stepEndTWR > stage.maxThrustToWeight)
                        stage.maxThrustToWeight = stepEndTWR;

                    //MonoBehaviour.print("newMaxTWR = " + stage.maxThrustToWeight);

                    // If we have drained anything and the masses make sense then add this step's deltaV to the stage total
                    if (resourceDrainTime > 0d && stepStartMass > stepEndMass && stepStartMass > 0d && stepEndMass > 0d)
                        vecStageDeltaV += vecThrust * (float)((currentisp * STD_GRAVITY * Math.Log(stepStartMass / stepEndMass)) / simpleTotalThrust);

                    // Update the active engines and resource drains for the next step
                    UpdateResourceDrains();

                    // Recalculate the current thrust and isp for the next step
                    CalculateThrustAndISP();

                    // Check if we actually changed anything
                    if (stepStartMass == stepEndMass)
                    {
                        //MonoBehaviour.print("No change in mass");
                        break;
                    }

                    // Check to stop rampant looping
                    if (loopCounter == 1000)
                    {
                        MonoBehaviour.print("exceeded loop count");
                        MonoBehaviour.print("stageStartMass = " + stageStartMass);
                        MonoBehaviour.print("stepStartMass = " + stepStartMass);
                        MonoBehaviour.print("StepEndMass   = " + stepEndMass);
                        break;
                    }

                    // The next step starts at the mass this one ended at
                    stepStartMass = stepEndMass;
                }

                // Store more values in the Stage object and stick it in the array

                // Store the magnitude of the deltaV vector
                stage.deltaV = vecStageDeltaV.magnitude;

                // Recalculate effective stage isp from the stage deltaV (flip the standard deltaV calculation around)
                // Note: If the mass doesn't change then this is a divide by zero
                if (stageStartMass != stepStartMass)
                    stage.isp = stage.deltaV / (STD_GRAVITY * Math.Log(stageStartMass / stepStartMass));
                else
                    stage.isp = 0;

                // Zero stage time if more than a day (this should be moved into the window code)
                stage.time = (stageTime < SECONDS_PER_DAY) ? stageTime : 0d;
                stage.number = doingCurrent ? -1 : currentStage;                // Set the stage number to -1 if doing current engines
                stages[currentStage] = stage;

                // Now activate the next stage
                currentStage--;
                doingCurrent = false;

                if (log != null)
                {
                    // Log how long the stage took
                    _timer.Stop();
                    MonoBehaviour.print("Simulating stage took " + _timer.ElapsedMilliseconds + "ms");
                    stage.Dump();
                    _timer.Reset();
                    _timer.Start();
                }

                // Activate the next stage
                ActivateStage();

                if (log != null)
                {
                    // Log how long it took to activate
                    _timer.Stop();
                    MonoBehaviour.print("ActivateStage took " + _timer.ElapsedMilliseconds + "ms");
                }
            }

            // Now we add up the various total fields in the stages
            for (int i = 0; i < stages.Length; i++)
            {
                // For each stage we total up the cost, mass, deltaV and time for this stage and all the stages above
                for (int j = i; j >= 0; j--)
                {
                    stages[i].totalCost += stages[j].cost;
                    stages[i].totalMass += stages[j].mass;
                    stages[i].totalDeltaV += stages[j].deltaV;
                    stages[i].totalTime += stages[j].time;
                }
                // We also total up the deltaV for stage and all stages below
                for (int j = i; j < stages.Length; j++)
                {
                    stages[i].inverseTotalDeltaV += stages[j].deltaV;
                }

                // Zero the total time if the value will be huge (24 hours?) to avoid the display going weird
                // (this should be moved into the window code)
                if (stages[i].totalTime > SECONDS_PER_DAY)
                    stages[i].totalTime = 0d;
            }

            if (log != null)
            {
                _timer.Stop();
                MonoBehaviour.print("RunSimulation: " + _timer.ElapsedMilliseconds + "ms");
            }

            return stages;
        }
Example #10
0
        public Stage[] RunSimulation(double gravity, double atmosphere = 0)
        {
            currentStage = Staging.lastStage;
            Stage[] stages = new Stage[currentStage + 1];

            BuildVessel(this.partList, atmosphere);

            while (currentStage >= 0)
            {
                Stage stage = new Stage();
                double stageTime = 0d;
                double stageDeltaV = 0d;
                double totalStageThrust = 0d;
                double totalStageActualThrust = 0d;

                double totalStageFlowRate = 0d;
                double totalStageIspFlowRate = 0d;

                foreach (PartSim engine in ActiveEngines)
                {
                    totalStageActualThrust += engine.actualThrust;
                    totalStageThrust += engine.thrust;

                    totalStageFlowRate += engine.ResourceConsumptions.Mass;
                    totalStageIspFlowRate += engine.ResourceConsumptions.Mass * engine.isp;
                }

                if (totalStageFlowRate > 0d && totalStageIspFlowRate > 0d)
                {
                    stage.isp = totalStageIspFlowRate / totalStageFlowRate;
                }

                stage.thrust = totalStageThrust;
                stage.thrustToWeight = (double)(totalStageThrust / (ShipMass * gravity));
                stage.actualThrust = totalStageActualThrust;
                stage.actualThrustToWeight = (double)(totalStageActualThrust / (ShipMass * gravity));

                foreach (PartSim partSim in partSims)
                {
                    if (partSim.decoupledInStage == currentStage - 1)
                    {
                        stage.cost += partSim.part.partInfo.cost;
                        stage.mass += partSim.GetStartMass(currentStage);
                    }
                }

                int loopCounter = 0;
                while (!AllowedToStage())
                {
                    loopCounter++;

                    List<PartSim> engines = ActiveEngines;
                    totalStageThrust = 0d;
                    foreach (PartSim engine in engines)
                    {
                        if (engine.actualThrust > 0d)
                        {
                            totalStageThrust += engine.actualThrust;
                        }
                        else
                        {
                            totalStageThrust += engine.thrust;
                        }
                    }

                    SetResourceDrainRates();

                    double resourceDrainTime = double.MaxValue;
                    foreach (PartSim partSim in partSims)
                    {
                        double time = 0d;
                        time = partSim.TimeToDrainResource();
                        if (time < resourceDrainTime)
                        {
                            resourceDrainTime = time;
                        }
                    }

                    double startMass = ShipMass;
                    foreach (PartSim partSim in partSims)
                    {
                        partSim.DrainResources(resourceDrainTime);
                    }
                    double endMass = ShipMass;
                    stageTime += resourceDrainTime;

                    if (resourceDrainTime > 0d && startMass > endMass && startMass > 0d && endMass > 0d)
                    {
                        stageDeltaV += (stage.isp * STD_GRAVITY) * Math.Log(startMass / endMass);
                    }

                    if (loopCounter == 1000)
                    {
                        break;
                    }
                }

                stage.deltaV = stageDeltaV;
                if (stageTime < 9999)
                {
                    stage.time = stageTime;
                }
                else
                {
                    stage.time = 0d;
                }
                stages[currentStage] = stage;

                currentStage--;
                ActivateStage();
            }

            for (int i = 0; i < stages.Length; i++)
            {
                for (int j = i; j >= 0; j--)
                {
                    stages[i].totalCost += stages[j].cost;
                    stages[i].totalMass += stages[j].mass;
                    stages[i].totalDeltaV += stages[j].deltaV;
                    stages[i].totalTime += stages[j].time;
                }
                for (int j = i; j < stages.Length; j++)
                {
                    stages[i].inverseTotalDeltaV += stages[j].deltaV;
                }

                if (stages[i].totalTime > 9999d)
                {
                    stages[i].totalTime = 0d;
                }
            }

            return stages;
        }