1.) Why don't NASA experts reject the Vostok programme as a conspiracy?1) why? Did the Vostok missions not happen?
2.) How do ICBMs (intercontinental ballistic missiles) return to earth without burning completely in the atmosphere? (they have no heat shield and a high radial velocity before reentry)
1) why? Did the Vostok missions not happen?
2) are you sure they have "no" heat management? ICBMs payloads can be designed to handle higher temperatures than people could.
1.) Well, as I explained in the OP, I assume that NASA experts would think they could not happen.1) Again, why? As far as I know the vostok capsules did have a heat shield - a resin - but the composition was a little different. The vostok capsules were also spherical (as Neil's pictures show) and designed for limited control, so the heat shielding had to be on all sides. This increased weight. (Some Soviet systems also used metal heat shields which dispersed heat by radiation.) Just because the vostok program used a somewhat different technology does not mean it couldn't work.
2.) There is no known heat management, while impact speed is up to 7 km/s.
1) Again, why? As far as I know the vostok capsules did have a heat shield - a resin - but the composition was a little different. The vostok capsules were also spherical (as Neil's pictures show) and designed for limited control, so the heat shielding had to be on all sides. This increased weight. (Some Soviet systems also used metal heat shields which dispersed heat by radiation.) Just because the vostok program used a somewhat different technology does not mean it couldn't work.
2) ICBMs have reentry vehicles - vehicles designed for reentry. Usually MIRVs, multiple independent reentry vehicles per one ICBM. They are not protecting people, though, so they can use less shielding.
import static java.awt.BasicStroke.CAP_ROUND;
import static java.awt.BasicStroke.JOIN_ROUND;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
import static java.lang.Math.PI;
import static java.lang.Math.abs;
import static java.lang.Math.atan2;
import static java.lang.Math.cos;
import static java.lang.Math.exp;
import static java.lang.Math.sin;
import static java.lang.Math.sqrt;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.imageio.ImageIO;
/**
* Simulation of the re-entry of Yuri Gagarin.
*
* <pre>
* time accel max power max temp
* Result: 04'39" 23.5g 2879.84MW 7435K
* Horizontal initial speed 0m/s: 03'51" 4.2g 88.73MW 3115K
* Drag coefficient ten times: 08'52" 20.4g 2469.70MW 7155K
* </pre>
*
* <ul>
* <li>Re-entry takes four times less time than said 20min.</li>
* <li>Horizontal distance is three and a half times shorter than 4000km.</li>
* <li>Maximum temperature is much too high.</li>
* <li>With constant drag coefficient of 0.47 re-entry is a few percent faster.</li>
* <li>15cm diameter and 10kg: virtually same result (power is four times higher though)</li>
* </ul>
*
* @see https://en.wikipedia.org/wiki/Vostok_1
* @see https://de.wikipedia.org/wiki/Fall_mit_Luftwiderstand#Fall_mit_Luftwiderstand:_Newton-Reibung
* @see https://de.wikipedia.org/wiki/Methode_der_kleinen_Schritte
* @see https://de.wikipedia.org/wiki/Barometrische_Höhenformel
* @see https://de.wikipedia.org/wiki/Stefan-Boltzmann-Gesetz
* @see http://www.astronautix.com/v/vostok1.html
* @see http://www.spacefacts.de/mission/english/vostok-1.htm
* @see http://heiwaco.tripod.com/moontravelw1.htm#REE
*
* @author Struthio
* @since October 2018
*
*/
public class GagarinsReentry
{
@Doc("Diameter of the spherical capsule in m.")
private static final double d = 2.3;
@Doc("Weight of the spherical capsule in kg.")
private static final double m = 2400;
@Doc("Sectional area of the spherical capsule in m^2.")
private static final double Asectional = PI * sqr(0.5 * d);
@Doc("Surface area of the spherical capsule in m^2.")
private static final double Asurface = 4 * Asectional;
@Doc("Gravitational acceleration at sea level in m/s^2.")
private static final double g = 9.81;
@Doc("Radius of the earth in m.")
private static final double r = 6370000;
@Doc("Mass density of air at sea level in kg/m^3.")
private static final double rho0 = 1.293;
@Doc("Speed of sound in m/s.")
private static final double cAir = 331.5;
@Doc("Calculation time interval in s.")
private static final double dt = 0.01;
@Doc("Current time in s.")
private double t = 0;
@Doc("Horizontal distance m.")
private double x = 0;
@Doc("Height above sea level in m.")
private double y = 130000;
@Doc("Horizontal speed in m/s.")
private double vx = 8000;
@Doc("Vertical speed in m/s.")
private double vy = 0;
@Doc("Horizontal acceleration in m/s.")
private double ax = 0;
@Doc("Vertical acceleration in m/s.")
private double ay = 0;
@Doc("Mass density of air at current height above sea level in kg/m^3.")
private double rho = 0;
@Doc("Drag coefficient.")
private double cw = 0;
@Doc("Braking force in N")
private double F = 0;
@Doc("Braking power in W")
private double P = 0;
@Doc("Maximum braking force in N")
private double Pmax = 0;
@Doc("Maximum acceleration in m/s^2")
private double aMax = 0;
private final DragCoefficient dragCoefficient = new DragCoefficient();
private final List<List<Double>> signals = new ArrayList<>();
{
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
}
/**
* Program entry point.
* <p>
* prints text to stdout and opens a *.png-image in the systems image viewer.
*
* @param args
* arguments are ignored.
*/
public static void main(final String... args)
{
try
{
final GagarinsReentry reentry = new GagarinsReentry();
reentry.run();
final Plotter.Config config = new Plotter.Config("Re-entry Yuri Gagarin", "",
"y, Cw, T, \u03C1, y', y\"", reentry.time());
new Plotter(config, reentry.signals).openRasterImageInEditor();
}
catch (final Throwable t)
{
t.printStackTrace();
}
}
public GagarinsReentry()
{
}
private void run()
{
step(true);
printDoc();
out("\n");
out(" t[s] ax ay rho cw F vx vy x h P \n");
out("------ ------- ------- -------- -------- ----------- ------------ ------------ -------- -------- --------\n");
print();
int noOfSteps;
for (noOfSteps = 0; y > 0; noOfSteps++)
{
step(false);
if (noOfSteps % 10 == 0)
{
print();
}
}
if (noOfSteps % 10 != 0)
{
print();
}
out("noOfSteps: %d\n", noOfSteps);
out("%s %.1fg %.2fMW %.0fK\n", time(), aMax / g, 1E-6 * Pmax, temperatureInK(Pmax));
}
private void printDoc()
{
for (final Field field : GagarinsReentry.class.getDeclaredFields())
{
final Doc doc = field.getAnnotation(Doc.class);
if (doc != null)
{
final boolean accessible = field.isAccessible();
try
{
field.setAccessible(true);
final double value = (Double) field.get(this);
String sValue;
if (value == 0)
{
sValue = String.format(Locale.US, "%12s", "0");
}
else if (abs(value) < 0.001 || abs(value) > 1E8)
{
sValue = String.format(Locale.US, "%12.3E", value);
}
else
{
sValue = String.format(Locale.US, "%12.3f", value);
}
out("%12s = %s %s\n", field.getName(), sValue, doc.value());
}
catch (final Exception e)
{
throw new IllegalStateException("unreached", e);
}
finally
{
field.setAccessible(accessible);
}
}
}
}
private void print()
{
out("%s %7.2f %7.2f %8.2E %8.2f %10.2fN %8.2fkm/h %8.2fkm/h %7.0fm %7.0fm %6.1fMW\n", time(),
ax, ay, rho, cw, F, 3.6 * vx, 3.6 * vy, x, y, 1E-6 * P);
}
private String time()
{
final int s = (int) (t + 0.5);
return String.format("%02d'%02d\"", s / 60, s % 60);
}
private void step(final boolean initialize)
{
rho = rho0 * exp(-y / 8400);
final double v = sqrt(sqr(vx) + sqr(vy));
F = airFrictionForceInN(rho, y, v);
final double alpha = atan2(vy, vx);
final double Fx = F * cos(alpha);
final double Fy = F * sin(alpha);
ax = Fx / m;
ay = Fy / m - g * (r / (r + y));
if (!initialize)
{
t += dt;
vx += ax * dt;
vy += ay * dt;
x += vx * dt;
y += vy * dt;
}
final double a = sqrt(ax * ax + ay * ay);
if (aMax < a)
{
aMax = a;
}
P = m * v * a;
if (Pmax < P)
{
Pmax = P;
}
signals.get(0).add(y);
signals.get(1).add(vy);
signals.get(2).add(ay);
signals.get(3).add(cw);
signals.get(4).add(rho);
signals.get(5).add(temperatureInK(P));
}
/**
* Returns the temperature in Kelvin of the black sphere emitting the given power.
*/
private static double temperatureInK(final double powerInWatts)
{
// https://de.wikipedia.org/wiki/Stefan-Boltzmann-Gesetz
final double sigma = 5.670367E-8;
return sqrt(sqrt(powerInWatts / (sigma * Asurface)));
}
/**
* Returns the air friction force is Newtons.
*
* @param rho
* The mass desity of the air in kg/m^3.
* @param h
* The height above sea level.
* @param v
* The speed in m/s.
* @return the air friction force is Newtons.
* @throws IllegalArgumentException
* If the height above sea level exceeds 150km.
* @see https://de.wikipedia.org/wiki/Str%C3%B6mungswiderstandskoeffizient
*/
private double airFrictionForceInN(final double rho, final double h, final double v)
throws IllegalArgumentException
{
if (h > 150000)
{
throw new IllegalArgumentException("formula valid up to 150km height only");
}
cw = dragCoefficient.getValue(abs(v / cAir));
return -0.5 * rho * cw * Asectional * sqr(v);
}
private static double sqr(final double x)
{
return x * x;
}
private static void out(final String format, final Object... args)
{
System.out.format(Locale.US, format, args);
}
// unused - extract curve points from image
public static void _main(final String... args) throws IOException
{
final double dx = 6;
final double dy = 1.2;
final BufferedImage image = ImageIO.read(new File("drag.png"));
final int width = image.getWidth();
final int height = image.getHeight();
for (int x = 0; x < width; x += width / 100)
{
int y = 0;
for (int yy = height - 1; yy > 0; yy--, y++)
{
final int rgb = image.getRGB(x, yy);
final int brightness = (rgb & 0xFF) + (rgb >> 8 & 0xFF) + (rgb >> 16 & 0xFF);
if (brightness < 0x180)
{
break;
}
}
final double px = x * dx / width;
final double py = y * dy / height;
System.out.format(Locale.US, " { %7.5f, %7.5f },\n", px, py);
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
@interface Doc {
String value();
}
/**
* A function defined by a polygon.
*/
class Function
{
private final double[][] xyValues;
public Function(final double[][] xyValues)
{
this.xyValues = xyValues;
}
/**
* Returns {@code f(x)}.
*/
public double getValue(final double x)
{
double[] point = xyValues[0];
if (x <= point[0])
{
return point[1];
}
final int N = xyValues.length;
point = xyValues[N - 1];
if (x >= point[0])
{
return point[1];
}
for (int k = 1; k < N; k++)
{
point = xyValues[k];
if (x <= point[0])
{
final double[] prev = xyValues[k - 1];
final double dx = point[0] - prev[0];
final double dy = point[1] - prev[1];
return prev[1] + dy * (x - prev[0]) / dx;
}
}
throw new IllegalStateException("unreached");
}
}
/**
* The drag coefficient as a function of the mach number.
*
* Values generated semi-automatically from the image at
* {@code https://de.wikipedia.org/wiki/Str%C3%B6mungswiderstandskoeffizient}.
*/
class DragCoefficient extends Function
{
public DragCoefficient()
{
super(new double[][] { //
{ 0.00000, 0.46595 }, { 0.05928, 0.46965 }, { 0.11855, 0.47519 }, { 0.17783, 0.47889 },
{ 0.23710, 0.48259 }, { 0.29638, 0.48629 }, { 0.35565, 0.49183 }, { 0.41493, 0.49738 },
{ 0.47420, 0.50108 }, { 0.53348, 0.51032 }, { 0.59276, 0.52142 }, { 0.65203, 0.54176 },
{ 0.71131, 0.57319 }, { 0.77058, 0.61941 }, { 0.82986, 0.68043 }, { 0.88913, 0.74700 },
{ 0.94841, 0.80986 }, { 1.00768, 0.86533 }, { 1.06696, 0.90971 }, { 1.12623, 0.94299 },
{ 1.18551, 0.96518 }, { 1.24479, 0.97997 }, { 1.30406, 0.98737 }, { 1.36334, 0.99476 },
{ 1.42261, 0.99846 }, { 1.48189, 1.00031 }, { 1.54116, 1.00216 }, { 1.60044, 1.00216 },
{ 1.65971, 1.00216 }, { 1.71899, 1.00031 }, { 1.77827, 1.00031 }, { 1.83754, 0.99846 },
{ 1.89682, 0.99661 }, { 1.95609, 0.99476 }, { 2.01537, 0.99291 }, { 2.07464, 0.99106 },
{ 2.13392, 0.98921 }, { 2.19319, 0.98552 }, { 2.25247, 0.98367 }, { 2.31175, 0.98182 },
{ 2.37102, 0.97812 }, { 2.43030, 0.97627 }, { 2.48957, 0.97257 }, { 2.54885, 0.97072 },
{ 2.60812, 0.96703 }, { 2.66740, 0.96518 }, { 2.72667, 0.96148 }, { 2.78595, 0.95963 },
{ 2.84523, 0.95778 }, { 2.90450, 0.95593 }, { 2.96378, 0.95408 }, { 3.02305, 0.95223 },
{ 3.08233, 0.95039 }, { 3.14160, 0.94854 }, { 3.20088, 0.94669 }, { 3.26015, 0.94484 },
{ 3.31943, 0.94299 }, { 3.37870, 0.94114 }, { 3.43798, 0.93929 }, { 3.49726, 0.93744 },
{ 3.55653, 0.93559 }, { 3.61581, 0.93559 }, { 3.67508, 0.93374 }, { 3.73436, 0.93190 },
{ 3.79363, 0.93005 }, { 3.85291, 0.93005 }, { 3.91218, 0.92820 }, { 3.97146, 0.92635 },
{ 4.03074, 0.92635 }, { 4.09001, 0.92450 }, { 4.14929, 0.92265 }, { 4.20856, 0.92265 },
{ 4.26784, 0.92080 }, { 4.32711, 0.92080 }, { 4.38639, 0.91895 }, { 4.44566, 0.91895 },
{ 4.50494, 0.91710 }, { 4.56422, 0.91710 }, { 4.62349, 0.91525 }, { 4.68277, 0.91525 },
{ 4.74204, 0.91341 }, { 4.80132, 0.91341 }, { 4.86059, 0.91341 }, { 4.91987, 0.91156 },
{ 4.97914, 0.91156 }, { 5.03842, 0.91156 }, { 5.09769, 0.90971 }, { 5.15697, 0.90971 },
{ 5.21625, 0.90971 }, { 5.27552, 0.90971 }, { 5.33480, 0.90786 }, { 5.39407, 0.90786 },
{ 5.45335, 0.90786 }, { 5.51262, 0.90786 }, { 5.57190, 0.90786 }, { 5.63117, 0.90786 },
{ 5.69045, 0.90786 }, { 5.74973, 0.90786 }, { 5.80900, 0.90786 }, { 5.86828, 0.90786 },
{ 5.92755, 0.90786 }, { 5.98683, 0.90601 }, });
}
}
/**
* Plotter to show an image in the systems image viewer.
*
* @author Struthio
* @since October 2018
*/
class Plotter
{
private final int width;
private final int height;
private final Config config;
private final double[][] signals;
private final double samplesPerDiv;
public Plotter(final Config config, final List<List<Double>> signals)
{
this.config = config;
this.signals = new double[signals.size()][];
int maxLength = 0;
for (int n = 0; n < signals.size(); n++)
{
final List<Double> signal = signals.get(n);
final int N = signal.size();
if (maxLength < N)
{
maxLength = N;
}
this.signals[n] = new double[N];
for (int k = 0; k < N; k++)
{
this.signals[n][k] = signal.get(k);
}
normalize(this.signals[n]);
}
this.width = (2 * config.noOfMarginDivsX + config.noOfDivsX) * config.divWidth;
this.height = (2 * config.noOfMarginDivsY + config.noOfDivsY) * config.divHeight;
this.samplesPerDiv = maxLength / (double) config.noOfDivsX;
}
public void openRasterImageInEditor()
{
try
{
final File file = File.createTempFile(Plotter.class.getName(), ".png");
createRasterImageFile(file);
Desktop.getDesktop().edit(file);
}
catch (final IOException e)
{
throw new IllegalStateException("failed to create temporary image file", e);
}
catch (final HeadlessException e)
{
throw new IllegalStateException("platform not supported", e);
}
catch (final UnsupportedOperationException e)
{
throw new IllegalStateException("platform not supported", e);
}
}
private void createRasterImageFile(final File file) throws IOException
{
final RenderedImage image = createRasterImage();
ImageIO.write(image, "PNG", file);
}
private BufferedImage createRasterImage()
{
final BufferedImage image = new BufferedImage(width, height, TYPE_4BYTE_ABGR);
final Graphics2D graphics2D = image.createGraphics();
try
{
paint(graphics2D);
}
finally
{
graphics2D.dispose();
}
return image;
}
private void paint(final Graphics2D graphics2D)
{
graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
paintBackground(graphics2D);
paintGrid(graphics2D);
paintCurves(graphics2D);
}
private void paintBackground(final Graphics2D graphics2D)
{
graphics2D.setColor(config.bgColor);
graphics2D.fill(new Rectangle2D.Double(0d, 0d, width, height));
}
private void paintGrid(final Graphics2D graphics2D)
{
final String spd = String.valueOf((int) samplesPerDiv);
final String abscissaeText = String.format("%staps/div, %dtaps", spd, signals[0].length);
final String ordinatesText = String.format("%s/div", String.valueOf(2.0 / config.noOfDivsY));
final GridPlotter plotter = new GridPlotter(config, abscissaeText, ordinatesText);
plotter.plot(graphics2D);
}
private void paintCurves(final Graphics2D graphics2D)
{
final float penWidth = config.signalPenWidth * config.divWidth / 32f;
graphics2D.setStroke(new BasicStroke(penWidth, BasicStroke.CAP_ROUND, BasicStroke.CAP_ROUND));
final double x0 = config.noOfMarginDivsX * config.divWidth;
final double y0 = (config.noOfMarginDivsY + 0.5f * config.noOfDivsY) * config.divHeight;
final double scale = 0.5 * (config.noOfDivsY * config.divHeight);
for (int kSignal = 0; kSignal < signals.length; kSignal++)
{
plotCurve(graphics2D, kSignal, x0, y0, scale);
}
}
private void plotCurve(final Graphics2D graphics2D, final int kSignal, final double x0,
final double y0, final double scale)
{
final boolean samples = samplesPerDiv <= 10;
final Shape originalClip = graphics2D.getClip();
try
{
final Rectangle2D signalClip;
{
final double x = config.noOfMarginDivsX * config.divWidth - 0.25 * config.divWidth;
final double y = config.noOfMarginDivsY * config.divHeight - 0.25 * config.divHeight;
final double w = config.noOfDivsX * config.divWidth + 0.50 * config.divWidth;
final double h = config.noOfDivsY * config.divHeight + 0.50 * config.divHeight;
signalClip = new Rectangle2D.Double(x - 2, y - 2, w + 4, h + 4);
}
graphics2D.clip(signalClip);
plotSamplesOrCurve(graphics2D, kSignal, samples, x0, y0, scale, samplesPerDiv, signalClip,
originalClip);
}
finally
{
graphics2D.setClip(originalClip);
}
}
private void plotSamplesOrCurve(final Graphics2D graphics2D, final int kSignal,
final boolean samples, final double x0, final double y0, final double scale,
final double samplesPerDiv, final Shape signalClip, final Shape originalClip)
{
final double rx = 0.12 * config.divWidth;
final double ry = 0.12 * config.divHeight;
graphics2D.setColor(config.signalColors[kSignal % config.signalColors.length]);
final double[] signal = signals[kSignal];
double xPrev = 0;
double yPrev = 0;
for (int n = 0; n <= signal.length; n++)
{
final double value = signal[n % signal.length];
final double x = x0 + n * config.divWidth / samplesPerDiv;
final double y = y0 - scale * value;
if (samples)
{
if (0 <= n && n < signal.length)
{
graphics2D.draw(new Line2D.Double(x, y0, x, y));
if (signalClip.contains(x, y))
{
graphics2D.setClip(originalClip);
graphics2D.draw(new Ellipse2D.Double(x - 0.5 * rx, y - 0.5 * ry, rx, ry));
graphics2D.fill(new Ellipse2D.Double(x - 0.5 * rx, y - 0.5 * ry, rx, ry));
graphics2D.clip(signalClip);
}
}
}
else
{
graphics2D.clip(new Rectangle2D.Double(0, 0, width, height));
if (0 < n && n < signal.length)
{
graphics2D.draw(new Line2D.Double(xPrev, yPrev, x, y));
}
}
xPrev = x;
yPrev = y;
}
}
private static void normalize(final double[] array)
{
final int N = array.length;
if (N > 0)
{
double max = 0;
for (final double value : array)
{
final double c = abs(value);
if (max < c)
{
max = c;
}
}
if (max > 0 && max != 1)
{
final double scale = 1d / max;
for (int k = 0; k < N; k++)
{
array[k] *= scale;
}
}
}
}
private static final class GridPlotter
{
private final Config config;
private final String abscissaeText;
private final String ordinatesText;
public GridPlotter(final Config config, final String abscissaeText,
final String ordinatesText)
{
this.config = config;
this.abscissaeText = abscissaeText;
this.ordinatesText = ordinatesText;
}
public void plot(final Graphics2D graphics2D)
{
graphics2D.setColor(config.gridColor);
final double x0 = config.noOfMarginDivsX * config.divWidth;
final double x1 = (config.noOfMarginDivsX + config.noOfDivsX) * config.divWidth;
final double y0 = config.noOfMarginDivsY * config.divHeight;
final double y1 = (config.noOfMarginDivsY + config.noOfDivsY) * config.divHeight;
plot(graphics2D, x0, y0, x1, y1, abscissaeText, ordinatesText);
}
private void plot(final Graphics2D graphics2D, final double x0, final double y0,
final double x1, final double y1, final String abscissaeText,
final String ordinatesText)
{
final Composite composite = graphics2D.getComposite();
try
{
final float penWidth = config.framePenWidth * config.divWidth / 32f;
graphics2D.setStroke(new BasicStroke(penWidth, CAP_ROUND, JOIN_ROUND));
final double xm = (x0 + x1) / 2;
final double ym = (y0 + y1) / 2;
graphics2D.draw(new Line2D.Double(x0, y0, x1, y0));
graphics2D.draw(new Line2D.Double(x0, y1, x1, y1));
graphics2D.draw(new Line2D.Double(x0, y0, x0, y1));
graphics2D.draw(new Line2D.Double(x1, y0, x1, y1));
graphics2D.draw(new Line2D.Double(x0, ym, x1, ym));
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
config.gridOpacity));
for (double x = x0; x <= x1; x += config.divWidth)
{
graphics2D.draw(new Line2D.Double(x, y0, x, y1));
}
for (double y = y0; y <= y1; y += config.divHeight)
{
graphics2D.draw(new Line2D.Double(x0, y, x1, y));
}
final Font font = config.font.deriveFont(0.40f * config.divHeight);
final FontRenderContext frc = graphics2D.getFontRenderContext();
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
config.textOpacity));
if (config.topLeft != null && !config.topLeft.isEmpty())
{
final String text = config.topLeft;
final double x = x0;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h)
+ (config.noOfDivsY + 1) * config.divHeight;
final double dx = 0;
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (config.topCenter != null && !config.topCenter.isEmpty())
{
final String text = config.topCenter;
final double x = xm;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h)
+ (config.noOfDivsY + 1) * config.divHeight;
final double dx = 0.5 * bounds.getWidth();
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (config.topRight != null && !config.topRight.isEmpty())
{
final String text = config.topRight;
final double x = x1;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h)
+ (config.noOfDivsY + 1) * config.divHeight;
final double dx = bounds.getWidth();
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (config.bottomRight != null && !config.bottomRight.isEmpty())
{
final String text = config.bottomRight;
final double x = x1;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h);
final double dx = bounds.getWidth();
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (abscissaeText != null && !abscissaeText.isEmpty())
{
final String text = abscissaeText;
final double x = x0;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h);
final double dx = x == xm ? 0.5 * bounds.getWidth() : 0;
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (ordinatesText != null && !ordinatesText.isEmpty())
{
final String text = ordinatesText;
graphics2D.setFont(font.deriveFont(AffineTransform.getQuadrantRotateInstance(-1)));
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double d = 0.5 * (config.divHeight - h);
graphics2D.drawString(text, (float) (x0 - d), (float) y1);
}
}
finally
{
graphics2D.setComposite(composite);
}
}
}
public static class Config
{
public final int divWidth = 48;
public final int divHeight = 48;
public final int noOfDivsX = 14;
public final int noOfDivsY = 8;
public final int noOfMarginDivsX = 1;
public final int noOfMarginDivsY = 1;
public final Color bgColor = new Color(0xEF, 0xFF, 0xEF);
public final Color gridColor = Color.LIGHT_GRAY;
public final Color[] signalColors = new Color[] { //
//
new Color(0xE0, 0x00, 0x00), //
new Color(0xE0, 0x00, 0x40), //
new Color(0xE0, 0x00, 0x80), //
new Color(0x00, 0x70, 0xE0), //
new Color(0x70, 0x00, 0xE0), //
new Color(0x70, 0xE0, 0x70), //
};
public final Font font = new Font("Comic Sans MS", Font.PLAIN, 1);
public final float framePenWidth = 1.0f;
public final float gridPenWidth = 0.3f;
public final float signalPenWidth = 0.8f;
public final float gridOpacity = 1.f;
public final float textOpacity = 1.f;
public final String topLeft;
public final String topCenter;
public final String topRight;
public final String bottomRight;
public Config(final String topLeft, final String topCenter, final String topRight,
final String bottomRight)
{
this.topLeft = topLeft;
this.topCenter = topCenter;
this.topRight = topRight;
this.bottomRight = bottomRight;
}
}
}
I made a simulation of Yuri [Gagarin's re-entry]. Below [are] the results as well as the source code of the software..
Gagarin is said to have [re-entered] the atmosphere in a [spherical] capsule of 2,400kg and 2.3m diameter. Re-entry starts at 130km height at a tangential velocity of 8,000m/s (28,800km/h). The plot shows:
(https://www.cathinfo.com/the-earth-god-made-flat-earth-geocentrism/reentry-possible/?action=dlattach;attach=12149;image)
- • time from 130km height down to sea level: 04'43" (history reports 20mins)
- • upper red curve: height over sea level
- • lower red curve: vertical speed (derivative of height)
- • red curve with peak up: vertical acceleration (2nd derivative of height)
- • green curve: Boltzmann-temperature (max 7438K) corresponding braking power (max 2885MW)
- • blue curve: speed dependent drag coefficient for newtonian air friction (0.47 at sea level)
- • purple curve: mass density of the atmosphere
- • horizontal speed not in plot, goes from 8000m/s to 0. Distance: 1182km (history reports 4000km).
More comments to follow.
.
import static java.awt.BasicStroke.CAP_ROUND;
import static java.awt.BasicStroke.JOIN_ROUND;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
import static java.lang.Math.PI;
import static java.lang.Math.abs;
import static java.lang.Math.atan2;
import static java.lang.Math.cos;
import static java.lang.Math.exp;
import static java.lang.Math.sin;
import static java.lang.Math.sqrt;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.imageio.ImageIO;
/**
* Simulation of the re-entry of Yuri Gagarin.
*
* @see https://en.wikipedia.org/wiki/Vostok_1
* @see https://de.wikipedia.org/wiki/Fall_mit_Luftwiderstand#Fall_mit_Luftwiderstand:_Newton-Reibung
* @see https://de.wikipedia.org/wiki/Methode_der_kleinen_Schritte
* @see https://de.wikipedia.org/wiki/Barometrische_Höhenformel
* @see https://de.wikipedia.org/wiki/Stefan-Boltzmann-Gesetz
* @see http://www.astronautix.com/v/vostok1.html
* @see http://www.spacefacts.de/mission/english/vostok-1.htm
* @see http://heiwaco.tripod.com/moontravelw1.htm#REE
*
* @see http://www.iaassconference2013.space-safety.org/wp-content/uploads/sites/32/2013/06/1600_Feistel.pdf
* @see http://articles.adsabs.harvard.edu/cgi-bin/nph-iarticle_query?2013ESASP.715E..75F&data_type=PDF_HIGH&whole_paper=YES&type=PRINTER&filetype=.pdf
*
* @author Struthio
* @since October 2018
*
*/
public class GagarinsReentry
{
/** Whether to use ATV-3 and not Gagarin. */
private static boolean ATV3 = false;
/** Title of output. */
private static final String title = "Re-entry " + (ATV3 ? "ATV-3" : "Yuri Gagarin");
@Doc("Drag coefficient of the shape of the capsule.")
private static final double cwShape = ATV3 ? 1.0 : 0.47;
@Doc("Length of cylidrical ATV-3 capsule in m.")
private static final double l = 10.27;
@Doc("Diameter of the spherical or cylindrical capsule in m.")
private static final double d = ATV3 ? 4.48 : 2.3;
@Doc("Weight of the capsule in kg.")
private static final double m = ATV3 ? 10470 : 2400;
@Doc("Sectional area of the capsule in m^2.")
private static final double Asectional = PI * sqr(0.5 * d);
@Doc("Surface area of the capsule in m^2.")
private static final double Asurface = ATV3 ? 2 * Asectional + PI * d * l : 4 * Asectional;
@Doc("Gravitational acceleration at sea level in m/s^2.")
private static final double g = 9.81;
@Doc("Radius of the earth in m.")
private static final double r = 6370000;
@Doc("Mass density of air at sea level in kg/m^3.")
private static final double rho0 = 1.293;
@Doc("Speed of sound in m/s.")
private static final double cAir = 331.5;
@Doc("Calculation time interval in s.")
private static final double dt = 0.01;
@Doc("Current time in s.")
private double t = 0;
@Doc("Horizontal distance m.")
private double x = 0;
@Doc("Height above sea level in m.")
private double y = ATV3 ? 120000d : 130000d;
@Doc("Initial flight path angle in rad.")
private static final double argV = (ATV3 ? -1.663 : -2.0) * PI / 180d;
@Doc("Initial velocity.")
private static final double absV = ATV3 ? 7593.0 : 8000;
@Doc("Horizontal velocity in m/s.")
private double vx = absV * cos(argV);
@Doc("Vertical velocity in m/s.")
private double vy = absV * sin(argV);
@Doc("Horizontal acceleration in m/s.")
private double ax = 0;
@Doc("Vertical acceleration in m/s.")
private double ay = 0;
@Doc("Mass density of air at current height above sea level in kg/m^3.")
private double rho = 0;
@Doc("Drag coefficient.")
private double cw = 0;
@Doc("Braking force in N")
private double F = 0;
@Doc("Braking power in W")
private double P = 0;
@Doc("Maximum braking force in N")
private double Pmax = 0;
@Doc("Maximum acceleration in m/s^2")
private double aMax = 0;
private final DragCoefficient dragCoefficient = new DragCoefficient();
private final List<List<Double>> signals = new ArrayList<>();
{
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
signals.add(new ArrayList<>());
}
/**
* Program entry point.
* <p>
* prints text to stdout and opens a *.png-image in the systems image viewer.
*
* @param args
* arguments are ignored.
*/
public static void main(final String... args)
{
try
{
final GagarinsReentry reentry = new GagarinsReentry();
reentry.run();
final Plotter.Config config = new Plotter.Config(title, "", "y, Cw, T, \u03C1, y', y\"",
reentry.time());
new Plotter(config, reentry.signals).openRasterImageInEditor();
}
catch (final Throwable t)
{
t.printStackTrace();
}
}
public GagarinsReentry()
{
}
private void run()
{
final double Ekin = 0.5 * m * (sqr(vx) + sqr(vy));
step(true);
out("%s\n", title);
out("\n");
printDoc();
out("\n");
out(" t[s] ax ay rho cw F vx vy x h P \n");
out("------ ------- ------- -------- -------- ----------- ------------ ------------ -------- -------- --------\n");
print();
int noOfSteps;
for (noOfSteps = 0; y > 0; noOfSteps++)
{
step(false);
if (noOfSteps % 100 == 0)
{
print();
}
}
if (noOfSteps % 10 != 0)
{
print();
}
out("noOfSteps: %d\n", noOfSteps);
out("%s %.1fg %.2fMW %.0fK\n", time(), aMax / g, 1E-6 * Pmax, temperatureInK(Pmax));
out("\n");
final double P = Ekin / t;
out("mean: %.2fMW %.0fK\n", 1E-6 * P, temperatureInK(P));
out("total energy: %.2fGJ\n", 1E-9 * Ekin);
}
private void printDoc()
{
for (final Field field : GagarinsReentry.class.getDeclaredFields())
{
final Doc doc = field.getAnnotation(Doc.class);
if (doc != null)
{
final boolean accessible = field.isAccessible();
try
{
field.setAccessible(true);
final double value = (Double) field.get(this);
String sValue;
if (value == 0)
{
sValue = String.format(Locale.US, "%12s", "0");
}
else if (abs(value) < 0.001 || abs(value) > 1E8)
{
sValue = String.format(Locale.US, "%12.3E", value);
}
else
{
sValue = String.format(Locale.US, "%12.3f", value);
}
out("%12s = %s %s\n", field.getName(), sValue, doc.value());
}
catch (final Exception e)
{
throw new IllegalStateException("unreached", e);
}
finally
{
field.setAccessible(accessible);
}
}
}
}
private void print()
{
out("%s %7.2f %7.2f %8.2E %8.2f %10.2fN %8.2fkm/h %8.2fkm/h %7.0fm %7.0fm %6.1fMW\n", time(),
ax, ay, rho, cw, F, 3.6 * vx, 3.6 * vy, x, y, 1E-6 * P);
}
private String time()
{
final int s = (int) (t + 0.5);
return String.format("%02d'%02d\"", s / 60, s % 60);
}
private void step(final boolean initialize)
{
rho = rho0 * exp(-y / 8400);
final double absV = sqrt(sqr(vx) + sqr(vy));
final double argV = atan2(vy, vx);
F = airFrictionForceInN(rho, y, absV);
final double aF = F / m; // air friction acceleration
final double aG = -g * (r / (r + y)); // gravitational acceleration
final double aC = sqr(vx) / (r + y); // centrifugal acceleration
ax = aF * cos(argV);
ay = aF * sin(argV) + aG + aC;
if (!initialize)
{
t += dt;
vx += ax * dt;
vy += ay * dt;
x += vx * dt;
y += vy * dt;
}
final double a = sqrt(ax * ax + ay * ay);
if (aMax < a)
{
aMax = a;
}
P = m * absV * a;
if (Pmax < P)
{
Pmax = P;
}
signals.get(0).add(y);
// signals.get(1).add(vy);
// signals.get(2).add(ay);
signals.get(1).add(sqrt(sqr(vx) + sqr(vy)));
signals.get(2).add(sqrt(sqr(ax) + sqr(ay)));
signals.get(3).add(cw);
signals.get(4).add(rho);
signals.get(5).add(temperatureInK(P));
// signals.get(6).add(x);
}
/**
* Returns the temperature in Kelvin of the black sphere emitting the given power.
*/
private static double temperatureInK(final double powerInWatts)
{
// https://de.wikipedia.org/wiki/Stefan-Boltzmann-Gesetz
final double sigma = 5.670367E-8;
return sqrt(sqrt(powerInWatts / (sigma * Asurface)));
}
/**
* Returns the air friction force is Newtons.
*
* @param rho
* The mass desity of the air in kg/m^3.
* @param h
* The height above sea level.
* @param v
* The speed in m/s.
* @return the air friction force is Newtons.
* @throws IllegalArgumentException
* If the height above sea level exceeds 150km.
* @see https://de.wikipedia.org/wiki/Str%C3%B6mungswiderstandskoeffizient
*/
private double airFrictionForceInN(final double rho, final double h, final double v)
throws IllegalArgumentException
{
if (h > 150000)
{
throw new IllegalArgumentException("formula valid up to 150km height only");
}
cw = cwShape / 0.47 * dragCoefficient.getValue(abs(v / cAir));
return -0.5 * rho * cw * Asectional * sqr(v);
}
private static double sqr(final double x)
{
return x * x;
}
private static void out(final String format, final Object... args)
{
System.out.format(Locale.US, format, args);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
@interface Doc {
String value();
}
/**
* A function defined by a polygon.
*/
class Function
{
private final double[][] xyValues;
public Function(final double[][] xyValues)
{
this.xyValues = xyValues;
}
/**
* Returns {@code f(x)}.
*/
public double getValue(final double x)
{
double[] point = xyValues[0];
if (x <= point[0])
{
return point[1];
}
final int N = xyValues.length;
point = xyValues[N - 1];
if (x >= point[0])
{
return point[1];
}
for (int k = 1; k < N; k++)
{
point = xyValues[k];
if (x <= point[0])
{
final double[] prev = xyValues[k - 1];
final double dx = point[0] - prev[0];
final double dy = point[1] - prev[1];
return prev[1] + dy * (x - prev[0]) / dx;
}
}
throw new IllegalStateException("unreached");
}
}
/**
* The drag coefficient as a function of the mach number.
*
* Values generated semi-automatically from the image at
* {@code https://de.wikipedia.org/wiki/Str%C3%B6mungswiderstandskoeffizient}.
*/
class DragCoefficient extends Function
{
public DragCoefficient()
{
super(new double[][] { //
{ 0.00000, 0.46595 }, { 0.05928, 0.46965 }, { 0.11855, 0.47519 }, { 0.17783, 0.47889 },
{ 0.23710, 0.48259 }, { 0.29638, 0.48629 }, { 0.35565, 0.49183 }, { 0.41493, 0.49738 },
{ 0.47420, 0.50108 }, { 0.53348, 0.51032 }, { 0.59276, 0.52142 }, { 0.65203, 0.54176 },
{ 0.71131, 0.57319 }, { 0.77058, 0.61941 }, { 0.82986, 0.68043 }, { 0.88913, 0.74700 },
{ 0.94841, 0.80986 }, { 1.00768, 0.86533 }, { 1.06696, 0.90971 }, { 1.12623, 0.94299 },
{ 1.18551, 0.96518 }, { 1.24479, 0.97997 }, { 1.30406, 0.98737 }, { 1.36334, 0.99476 },
{ 1.42261, 0.99846 }, { 1.48189, 1.00031 }, { 1.54116, 1.00216 }, { 1.60044, 1.00216 },
{ 1.65971, 1.00216 }, { 1.71899, 1.00031 }, { 1.77827, 1.00031 }, { 1.83754, 0.99846 },
{ 1.89682, 0.99661 }, { 1.95609, 0.99476 }, { 2.01537, 0.99291 }, { 2.07464, 0.99106 },
{ 2.13392, 0.98921 }, { 2.19319, 0.98552 }, { 2.25247, 0.98367 }, { 2.31175, 0.98182 },
{ 2.37102, 0.97812 }, { 2.43030, 0.97627 }, { 2.48957, 0.97257 }, { 2.54885, 0.97072 },
{ 2.60812, 0.96703 }, { 2.66740, 0.96518 }, { 2.72667, 0.96148 }, { 2.78595, 0.95963 },
{ 2.84523, 0.95778 }, { 2.90450, 0.95593 }, { 2.96378, 0.95408 }, { 3.02305, 0.95223 },
{ 3.08233, 0.95039 }, { 3.14160, 0.94854 }, { 3.20088, 0.94669 }, { 3.26015, 0.94484 },
{ 3.31943, 0.94299 }, { 3.37870, 0.94114 }, { 3.43798, 0.93929 }, { 3.49726, 0.93744 },
{ 3.55653, 0.93559 }, { 3.61581, 0.93559 }, { 3.67508, 0.93374 }, { 3.73436, 0.93190 },
{ 3.79363, 0.93005 }, { 3.85291, 0.93005 }, { 3.91218, 0.92820 }, { 3.97146, 0.92635 },
{ 4.03074, 0.92635 }, { 4.09001, 0.92450 }, { 4.14929, 0.92265 }, { 4.20856, 0.92265 },
{ 4.26784, 0.92080 }, { 4.32711, 0.92080 }, { 4.38639, 0.91895 }, { 4.44566, 0.91895 },
{ 4.50494, 0.91710 }, { 4.56422, 0.91710 }, { 4.62349, 0.91525 }, { 4.68277, 0.91525 },
{ 4.74204, 0.91341 }, { 4.80132, 0.91341 }, { 4.86059, 0.91341 }, { 4.91987, 0.91156 },
{ 4.97914, 0.91156 }, { 5.03842, 0.91156 }, { 5.09769, 0.90971 }, { 5.15697, 0.90971 },
{ 5.21625, 0.90971 }, { 5.27552, 0.90971 }, { 5.33480, 0.90786 }, { 5.39407, 0.90786 },
{ 5.45335, 0.90786 }, { 5.51262, 0.90786 }, { 5.57190, 0.90786 }, { 5.63117, 0.90786 },
{ 5.69045, 0.90786 }, { 5.74973, 0.90786 }, { 5.80900, 0.90786 }, { 5.86828, 0.90786 },
{ 5.92755, 0.90786 }, { 5.98683, 0.90601 }, });
}
}
/**
* Plotter to show an image in the systems image viewer.
*
* @author Struthio
* @since October 2018
*/
class Plotter
{
private final int width;
private final int height;
private final Config config;
private final double[][] signals;
private final double[] xValues;
private final double samplesPerDiv;
public Plotter(final Config config, final List<List<Double>> signals)
{
this.config = config;
this.signals = new double[signals.size()][];
this.xValues = null;
int maxLength = 0;
for (int n = 0; n < signals.size(); n++)
{
final List<Double> signal = signals.get(n);
final int N = signal.size();
if (maxLength < N)
{
maxLength = N;
}
this.signals[n] = new double[N];
for (int k = 0; k < N; k++)
{
this.signals[n][k] = signal.get(k);
}
normalize(this.signals[n]);
}
this.width = (2 * config.noOfMarginDivsX + config.noOfDivsX) * config.divWidth;
this.height = (2 * config.noOfMarginDivsY + config.noOfDivsY) * config.divHeight;
this.samplesPerDiv = maxLength / (double) config.noOfDivsX;
}
public void openRasterImageInEditor()
{
try
{
final File file = File.createTempFile(Plotter.class.getName(), ".png");
createRasterImageFile(file);
Desktop.getDesktop().edit(file);
}
catch (final IOException e)
{
throw new IllegalStateException("failed to create temporary image file", e);
}
catch (final HeadlessException e)
{
throw new IllegalStateException("platform not supported", e);
}
catch (final UnsupportedOperationException e)
{
throw new IllegalStateException("platform not supported", e);
}
}
private void createRasterImageFile(final File file) throws IOException
{
final RenderedImage image = createRasterImage();
ImageIO.write(image, "PNG", file);
}
private BufferedImage createRasterImage()
{
final BufferedImage image = new BufferedImage(width, height, TYPE_4BYTE_ABGR);
final Graphics2D graphics2D = image.createGraphics();
try
{
paint(graphics2D);
}
finally
{
graphics2D.dispose();
}
return image;
}
private void paint(final Graphics2D graphics2D)
{
graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
paintBackground(graphics2D);
paintGrid(graphics2D);
paintCurves(graphics2D);
}
private void paintBackground(final Graphics2D graphics2D)
{
graphics2D.setColor(config.bgColor);
graphics2D.fill(new Rectangle2D.Double(0d, 0d, width, height));
}
private void paintGrid(final Graphics2D graphics2D)
{
final String spd = String.valueOf((int) samplesPerDiv);
final String abscissaeText = String.format("%staps/div, %dtaps", spd, signals[0].length);
final String ordinatesText = String.format("%s/div", String.valueOf(2.0 / config.noOfDivsY));
final GridPlotter plotter = new GridPlotter(config, abscissaeText, ordinatesText);
plotter.plot(graphics2D);
}
private void paintCurves(final Graphics2D graphics2D)
{
final float penWidth = config.signalPenWidth * config.divWidth / 32f;
graphics2D.setStroke(new BasicStroke(penWidth, BasicStroke.CAP_ROUND, BasicStroke.CAP_ROUND));
final double x0 = config.noOfMarginDivsX * config.divWidth;
final double y0 = (config.noOfMarginDivsY + 0.5f * config.noOfDivsY) * config.divHeight;
for (int kSignal = 0; kSignal < signals.length; kSignal++)
{
plotCurve(graphics2D, kSignal, x0, y0);
}
}
private void plotCurve(final Graphics2D graphics2D, final int kSignal, final double x0,
final double y0)
{
final boolean samples = samplesPerDiv <= 10;
final Shape originalClip = graphics2D.getClip();
try
{
final Rectangle2D signalClip;
{
final double x = config.noOfMarginDivsX * config.divWidth - 0.25 * config.divWidth;
final double y = config.noOfMarginDivsY * config.divHeight - 0.25 * config.divHeight;
final double w = config.noOfDivsX * config.divWidth + 0.50 * config.divWidth;
final double h = config.noOfDivsY * config.divHeight + 0.50 * config.divHeight;
signalClip = new Rectangle2D.Double(x - 2, y - 2, w + 4, h + 4);
}
graphics2D.clip(signalClip);
plotSamplesOrCurve(graphics2D, kSignal, samples, x0, y0, samplesPerDiv, signalClip,
originalClip);
}
finally
{
graphics2D.setClip(originalClip);
}
}
private void plotSamplesOrCurve(final Graphics2D graphics2D, final int kSignal,
final boolean samples, final double x0, final double y0, final double samplesPerDiv,
final Shape signalClip, final Shape originalClip)
{
final double rx = 0.12 * config.divWidth;
final double ry = 0.12 * config.divHeight;
graphics2D.setColor(config.signalColors[kSignal % config.signalColors.length]);
final double scaleX = 0.5 * (config.noOfDivsX * config.divHeight);
final double scaleY = 0.5 * (config.noOfDivsY * config.divHeight);
final double[] signal = signals[kSignal];
if (signal.length < 2)
{
return;
}
double xPrev = 0;
double yPrev = 0;
for (int n = 0; n <= signal.length; n++)
{
final int k = n % signal.length;
final double vx = xValues != null ? scaleX * xValues[k]
: k * config.divWidth / samplesPerDiv;
final double vy = scaleY * signal[k];
final double x = x0 + vx;
final double y = y0 - vy;
if (samples)
{
if (0 <= n && n < signal.length)
{
graphics2D.draw(new Line2D.Double(x, y0, x, y));
if (signalClip.contains(x, y))
{
graphics2D.setClip(originalClip);
graphics2D.draw(new Ellipse2D.Double(x - 0.5 * rx, y - 0.5 * ry, rx, ry));
graphics2D.fill(new Ellipse2D.Double(x - 0.5 * rx, y - 0.5 * ry, rx, ry));
graphics2D.clip(signalClip);
}
}
}
else
{
graphics2D.clip(new Rectangle2D.Double(0, 0, width, height));
if (0 < n && n < signal.length)
{
graphics2D.draw(new Line2D.Double(xPrev, yPrev, x, y));
}
}
xPrev = x;
yPrev = y;
}
}
private static void normalize(final double[] array)
{
final int N = array.length;
if (N > 0)
{
double max = 0;
for (final double value : array)
{
final double c = abs(value);
if (max < c)
{
max = c;
}
}
if (max > 0 && max != 1)
{
final double scale = 1d / max;
for (int k = 0; k < N; k++)
{
array[k] *= scale;
}
}
}
}
private static final class GridPlotter
{
private final Config config;
private final String abscissaeText;
private final String ordinatesText;
public GridPlotter(final Config config, final String abscissaeText,
final String ordinatesText)
{
this.config = config;
this.abscissaeText = abscissaeText;
this.ordinatesText = ordinatesText;
}
public void plot(final Graphics2D graphics2D)
{
graphics2D.setColor(config.gridColor);
final double x0 = config.noOfMarginDivsX * config.divWidth;
final double x1 = (config.noOfMarginDivsX + config.noOfDivsX) * config.divWidth;
final double y0 = config.noOfMarginDivsY * config.divHeight;
final double y1 = (config.noOfMarginDivsY + config.noOfDivsY) * config.divHeight;
plot(graphics2D, x0, y0, x1, y1, abscissaeText, ordinatesText);
}
private void plot(final Graphics2D graphics2D, final double x0, final double y0,
final double x1, final double y1, final String abscissaeText,
final String ordinatesText)
{
final Composite composite = graphics2D.getComposite();
try
{
final float penWidth = config.framePenWidth * config.divWidth / 32f;
graphics2D.setStroke(new BasicStroke(penWidth, CAP_ROUND, JOIN_ROUND));
final double xm = (x0 + x1) / 2;
final double ym = (y0 + y1) / 2;
graphics2D.draw(new Line2D.Double(x0, y0, x1, y0));
graphics2D.draw(new Line2D.Double(x0, y1, x1, y1));
graphics2D.draw(new Line2D.Double(x0, y0, x0, y1));
graphics2D.draw(new Line2D.Double(x1, y0, x1, y1));
graphics2D.draw(new Line2D.Double(x0, ym, x1, ym));
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
config.gridOpacity));
for (double x = x0; x <= x1; x += config.divWidth)
{
graphics2D.draw(new Line2D.Double(x, y0, x, y1));
}
for (double y = y0; y <= y1; y += config.divHeight)
{
graphics2D.draw(new Line2D.Double(x0, y, x1, y));
}
final Font font = config.font.deriveFont(0.40f * config.divHeight);
final FontRenderContext frc = graphics2D.getFontRenderContext();
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
config.textOpacity));
if (config.topLeft != null && !config.topLeft.isEmpty())
{
final String text = config.topLeft;
final double x = x0;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h)
+ (config.noOfDivsY + 1) * config.divHeight;
final double dx = 0;
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (config.topCenter != null && !config.topCenter.isEmpty())
{
final String text = config.topCenter;
final double x = xm;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h)
+ (config.noOfDivsY + 1) * config.divHeight;
final double dx = 0.5 * bounds.getWidth();
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (config.topRight != null && !config.topRight.isEmpty())
{
final String text = config.topRight;
final double x = x1;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h)
+ (config.noOfDivsY + 1) * config.divHeight;
final double dx = bounds.getWidth();
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (config.bottomRight != null && !config.bottomRight.isEmpty())
{
final String text = config.bottomRight;
final double x = x1;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h);
final double dx = bounds.getWidth();
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (abscissaeText != null && !abscissaeText.isEmpty())
{
final String text = abscissaeText;
final double x = x0;
graphics2D.setFont(font);
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double dy = 0.5 * (config.divHeight - h);
final double dx = x == xm ? 0.5 * bounds.getWidth() : 0;
graphics2D.drawString(text, (float) (x - dx), (float) (y1 + config.divHeight - dy));
}
if (ordinatesText != null && !ordinatesText.isEmpty())
{
final String text = ordinatesText;
graphics2D.setFont(font.deriveFont(AffineTransform.getQuadrantRotateInstance(-1)));
final TextLayout layout = new TextLayout(text, font, frc);
final Rectangle2D bounds = layout.getBounds();
final double h = bounds.getHeight();
final double d = 0.5 * (config.divHeight - h);
graphics2D.drawString(text, (float) (x0 - d), (float) y1);
}
}
finally
{
graphics2D.setComposite(composite);
}
}
}
public static class Config
{
public final int divWidth = 48;
public final int divHeight = 48;
public final int noOfDivsX = 16;
public final int noOfDivsY = 10;
public final int noOfMarginDivsX = 1;
public final int noOfMarginDivsY = 1;
public final Color bgColor = new Color(0xEF, 0xFF, 0xEF);
public final Color gridColor = Color.LIGHT_GRAY;
public final Color[] signalColors = new Color[] { //
//
new Color(0xE0, 0x00, 0x00), //
new Color(0xE0, 0x00, 0x40), //
new Color(0xE0, 0x00, 0x80), //
new Color(0x00, 0x70, 0xE0), //
new Color(0x70, 0x00, 0xE0), //
new Color(0x70, 0xE0, 0x70), //
new Color(0x00, 0x00, 0xE0), //
};
public final Font font = new Font("Comic Sans MS", Font.PLAIN, 1);
public final float framePenWidth = 1.0f;
public final float gridPenWidth = 0.3f;
public final float signalPenWidth = 0.8f;
public final float gridOpacity = 1.f;
public final float textOpacity = 1.f;
public final String topLeft;
public final String topCenter;
public final String topRight;
public final String bottomRight;
public Config(final String topLeft, final String topCenter, final String topRight,
final String bottomRight)
{
this.topLeft = topLeft;
this.topCenter = topCenter;
this.topRight = topRight;
this.bottomRight = bottomRight;
}
}
}
Heat Shield(http://104.131.251.97/spacecraft/wp-content/uploads/sites/18/2015/09/7140970_orig-512x384.jpg)Photo: NASATo withstand re-entry heating of up to 2,800 degrees Celsius when returning from Mars, the Orion spacecraft is equipped with the world’s most powerful heat shield which also is the largest ever built with a diameter of just over five meters.The heat shield uses a titanium skeleton that provides the interface points with the crew module and adds strength to the heat shield required for it to withstand the impact with the water at splashdown. The skeleton is held in place by six brackets on the CM aft bulkhead. Fitted atop the skeleton is a carbon fiber skin that provides additional strength and acts as mounting surface for the AVCOAT ablative heat shield material. This structure consists of one center, 18 gore and 18 shoulder panels.Originally developed by Avco, the AVCOAT technology is currently being provided by Textron and consists of an empty fiberglass-phenolic honeycomb structure that is attached to the carbon fiber structure and contains over 330,000 empty cells.These cells within the honeycomb are then filled with the AVCOAT material using a hand gun. The AVCOAT layer is about 4 centimeters thick, 20% of that are expected to burn away during entry. The ablative material itself is an epoxy novolac resin with a number of additives to create a substance with a low density of 0.51g/cm³. During the re-entry process, pyrolysis of the material converts the material into a mixture of carbon and silica.Titanium Skeleton, Heat Shield Skin & Skin-Skeleton Mate(http://104.131.251.97/spacecraft/wp-content/uploads/sites/18/2015/09/Heat-Shield-Components-1024x235.jpg)Photos: NASA
(http://104.131.251.97/spacecraft/wp-content/uploads/sites/18/2015/09/2413374_orig-512x342.jpg)AVCOAT Application Technique – Photo: NASAThe principle behind ablative heat shield technology is to create a boundary layer between the shield’s outer wall and the extremely hot shock layer gas by allowing the heat shield material to slowly burn away and, in the process, generate gaseous reaction products that flow out of the heat shield and keep the shock layer at a separation distance, reducing the overall heat flux experienced by the outer shell of the spacecraft.The processes occurring at the heat shield material include a charring, melting and sublimation on the one hand and pyrolysis on the other. Pyrolysis creates the product gases that are blowing outward and create the desired blockage of convective and catalytic heat flux. Radiative heat flux is reduced by introducing carbon compounds into the boundary layer gas which make it optically opaque.Orion’s heat shield is launched with a reflective cover installed over it to protect it from the cold temperatures encountered in space. This cover burns away in the initial stages of re-entry.The current heat shield design may require modifications to the manufacturing process since the hand-filled AVCOAT material was more uneven than desired when Orion’s first heat shield rolled off the manufacturing line. Changes may also be necessary to fully certify the heat shield for re-entry energies occurring in Mars missions as the current version is only suitable for entry energies of lunar flights.
Now let's descend down to sea level. Given the unrealistically high 20min or 1200s of travel time, and assuming unrealistically that braking power is constant, braking power isThis is, I think, the place you should look into more. You're using the equation for radiative heat transfer, as if the reentry vehicle heats up to this temperature and disperses heat by black body radiation.
P = 75GJ / 1200s = 62.5MW
The corresponding temperature (Stefan Boltzmann law (https://en.wikipedia.org/wiki/Stefan%E2%80%93Boltzmann_law)) is
2854K or 2580°C.
This is, I think, the place you should look into more. You're using the equation for radiative heat transfer, as if the reentry vehicle heats up to this temperature and disperses heat by black body radiation.
The vehicle heats up from the heat generated by the bow shock (of a blunt body reentry vehicle). This happens over a large area. Heat is transferred to the vehicle mostly by convection, with some by radiation. The heat load the vehicle has to handle is only a fraction of the overall energy dissipated in losing kinetic energy - most of that energy goes to the atmosphere.
Origen called the firmament “without doubt firm and solid” (First Homily on Genesis, FC 71). Ambrose, commenting on Genesis 1:6, said, “the specific solidity of this exterior firmament is meant” (Hexameron, FC 42.60). And Saint Augustine said the word firmament was used “to indicate not that it is motionless but that it is solid and that it constitutes an impassible boundary between the waters above and the waters below” (The Literal Meaning of Genesis, ACW 41.1.61).
I assume that the heat shield is ideal and emits all friction energy in form of radiation. Doing this, the surface of the heat shield has the Boltzmann-temperature.I believe some early ICBMs and Soviet testing used radiative heat shields, but I believe all manned missions from Gagarin on used ablative heat shields. Part of the heat shield melts and that is where a lot of the heat goes. Much more than goes to radiative heat transfer.
Alternatively, part of the energy/power may heat the vehicle. But that would have to be a small fraction of the 62.5MW which does not really make difference.
What does that have to do with the question whether a reentry from a low orbit is possible?There is no such thing as "re entry". Especially from low earth "orbit". The firmament sits as a dome over the earth and nothing gets outside of it because there's water on the upper side of it. Low earth orbit suggests there is an "outer space" where rockets go, and moon landings are done, but that has never been proven and is counter to what we know about the upper atmosphere which is an ether and not "space". Much of what NASA and RASA talk about regarding rockets and space is provably garbage.
I believe some early ICBMs and Soviet testing used radiative heat shields, but I believe all manned missions from Gagarin on used ablative heat shields. Part of the heat shield melts and that is where a lot of the heat goes. Much more than goes to radiative heat transfer..