/
Phase.cs
186 lines (153 loc) · 5.85 KB
/
Phase.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
* Copyright Lamont Granquist, Sebastien Gaggini and the MechJeb contributors
* SPDX-License-Identifier: LicenseRef-PD-hp OR Unlicense OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT OR LGPL-2.1+
*/
using System;
using System.Text;
using MechJebLib.Primitives;
using MechJebLib.PVG.Integrators;
using MechJebLib.Utils;
using static MechJebLib.Utils.Statics;
#nullable enable
namespace MechJebLib.PVG
{
public class Phase
{
public double m0;
public double thrust;
public double isp;
public double mf;
public double bt;
public double maxt;
public double mint;
public double ve;
public double a0;
public double tau;
public double mdot;
public double dv;
public double DropMass; // FIXME: unused
public bool OptimizeTime;
public bool Infinite = false;
private bool _analytic = true;
public bool Analytic
{
get => _analytic;
set
{
_ipvgIntegrator = null;
_analytic = value;
}
}
public bool Unguided;
public bool MassContinuity = false;
public bool LastFreeBurn = false;
public bool Normalized;
public int KSPStage;
public int MJPhase;
private IPVGIntegrator? _ipvgIntegrator;
private IPVGIntegrator _integrator => _ipvgIntegrator ??= GetIntegrator();
private IPVGIntegrator GetIntegrator()
{
if (Coast)
return new VacuumCoastAnalytic();
return Analytic ? (IPVGIntegrator)new VacuumThrustAnalytic() : new VacuumThrustIntegrator();
}
public bool Coast => thrust == 0;
public V3 u0;
public Phase DeepCopy()
{
var newphase = (Phase)MemberwiseClone();
return newphase;
}
private Phase(double m0, double thrust, double isp, double mf, double bt, int kspStage, int mjPhase)
{
KSPStage = kspStage;
MJPhase = mjPhase;
this.m0 = m0;
this.thrust = thrust;
this.isp = isp;
this.mf = mf;
this.bt = bt;
ve = isp * G0;
a0 = thrust / m0;
tau = thrust == 0 ? double.PositiveInfinity : ve / a0;
mdot = ve == 0 ? 0 : thrust / ve;
dv = thrust == 0 ? 0 : -ve * Math.Log(1 - bt / tau);
OptimizeTime = false;
}
public Phase Rescale(Scale scale)
{
Check.False(Normalized);
var phase = (Phase)MemberwiseClone();
phase.ve = ve / scale.VelocityScale;
phase.tau = tau / scale.TimeScale;
phase.mdot = mdot / scale.MdotScale;
phase.thrust = thrust / scale.ForceScale;
phase.bt = bt / scale.TimeScale;
phase.mint = mint / scale.TimeScale;
phase.maxt = maxt / scale.TimeScale;
phase.m0 = m0 / scale.MassScale;
phase.mf = mf / scale.MassScale;
phase.DropMass = DropMass / scale.MassScale;
phase.Normalized = true;
return phase;
}
public void Integrate(Vn y0, Vn yf, double t0, double tf)
{
_integrator.Integrate(y0, yf, this, t0, tf);
}
public void Integrate(Vn y0, Vn yf, double t0, double tf, Solution solution)
{
_integrator.Integrate(y0, yf, this, t0, tf, solution);
}
public static Phase NewStageUsingFinalMass(double m0, double mf, double isp, double bt, int kspStage, int mjPhase, bool optimizeTime = false,
bool unguided = false)
{
Check.PositiveFinite(m0);
Check.PositiveFinite(mf);
Check.PositiveFinite(isp);
Check.PositiveFinite(bt);
double mdot = (m0 - mf) / bt;
double thrust = mdot * (isp * G0);
Check.PositiveFinite(mdot);
Check.PositiveFinite(thrust);
var phase = new Phase(m0, thrust, isp, mf, bt, kspStage, mjPhase) { OptimizeTime = optimizeTime, Unguided = unguided };
return phase;
}
public static Phase NewStageUsingThrust(double m0, double thrust, double isp, double bt, int kspStage, int mjPhase, bool optimizeTime = false,
bool unguided = false)
{
Check.PositiveFinite(m0);
Check.PositiveFinite(thrust);
Check.PositiveFinite(isp);
Check.PositiveFinite(bt);
double mdot = thrust / (isp * G0);
double mf = m0 - mdot * bt;
Check.PositiveFinite(mdot);
Check.PositiveFinite(mf);
var phase = new Phase(m0, thrust, isp, mf, bt, kspStage, mjPhase) { OptimizeTime = optimizeTime, Unguided = unguided };
return phase;
}
public static Phase NewFixedCoast(double m0, double ct, int kspStage, int mjPhase)
{
return new Phase(m0, 0, 0, m0, ct, kspStage, mjPhase);
}
public static Phase NewOptimizedCoast(double m0, double mint, double maxt, int kspStage, int mjPhase)
{
var phase = new Phase(m0, 0, 0, m0, mint, kspStage, mjPhase) { OptimizeTime = true, mint = mint, maxt = maxt };
return phase;
}
public override string ToString()
{
var sb = new StringBuilder();
sb.Append($"stage: {KSPStage} m0: {m0} mf: {mf} thrust: {thrust} bt: {bt} isp: {isp} mdot: {mdot}");
if (OptimizeTime)
sb.Append(" (optimized)");
if (Infinite)
sb.Append(" (infinite)");
if (Unguided)
sb.Append(" (unguided)");
return sb.ToString();
}
}
}