80beb071e721e5d81b09a4e89debc0fe929b0aa5
[debian/openrocket] / src / net / sf / openrocket / simulation / BasicLandingStepper.java
1 package net.sf.openrocket.simulation;
2
3 import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
4 import net.sf.openrocket.rocketcomponent.RecoveryDevice;
5 import net.sf.openrocket.simulation.exception.SimulationException;
6 import net.sf.openrocket.util.Coordinate;
7 import net.sf.openrocket.util.MathUtil;
8
9 public class BasicLandingStepper extends AbstractSimulationStepper {
10         
11         private static final double RECOVERY_TIME_STEP = 0.5;
12         
13         
14         @Override
15         public SimulationStatus initialize(SimulationStatus status) throws SimulationException {
16                 return status;
17         }
18         
19         @Override
20         public void step(SimulationStatus status, double maxTimeStep) throws SimulationException {
21                 double totalCD = 0;
22                 double refArea = status.getConfiguration().getReferenceArea();
23                 
24                 // Get the atmospheric conditions
25                 AtmosphericConditions atmosphere = modelAtmosphericConditions(status);
26                 
27                 //// Local wind speed and direction
28                 Coordinate windSpeed = modelWindVelocity(status);
29                 Coordinate airSpeed = status.getRocketVelocity().add(windSpeed);
30                 
31                 // Get total CD
32                 double mach = airSpeed.length() / atmosphere.getMachSpeed();
33                 for (RecoveryDevice c : status.getDeployedRecoveryDevices()) {
34                         totalCD += c.getCD(mach) * c.getArea() / refArea;
35                 }
36                 
37                 // Compute drag force
38                 double dynP = (0.5 * atmosphere.getDensity() * airSpeed.length2());
39                 double dragForce = totalCD * dynP * refArea;
40                 MassData massData = calculateMassData(status);
41                 double mass = massData.getCG().weight;
42                 
43
44                 // Compute drag acceleration
45                 Coordinate linearAcceleration;
46                 if (airSpeed.length() > 0.001) {
47                         linearAcceleration = airSpeed.normalize().multiply(-dragForce / mass);
48                 } else {
49                         linearAcceleration = Coordinate.NUL;
50                 }
51                 
52                 // Add effect of gravity
53                 double gravity = modelGravity(status);
54                 linearAcceleration = linearAcceleration.sub(0, 0, gravity);
55                 
56
57                 // Select time step
58                 double timeStep = MathUtil.min(0.5 / linearAcceleration.length(), RECOVERY_TIME_STEP);
59                 
60                 // Perform Euler integration
61                 status.setRocketPosition(status.getRocketPosition().add(status.getRocketVelocity().multiply(timeStep)).
62                                 add(linearAcceleration.multiply(MathUtil.pow2(timeStep) / 2)));
63                 status.setRocketVelocity(status.getRocketVelocity().add(linearAcceleration.multiply(timeStep)));
64                 status.setSimulationTime(status.getSimulationTime() + timeStep);
65                 
66
67                 // Store data
68                 FlightDataBranch data = status.getFlightData();
69                 boolean extra = status.getSimulationConditions().isCalculateExtras();
70                 data.addPoint();
71                 
72                 data.setValue(FlightDataType.TYPE_TIME, status.getSimulationTime());
73                 data.setValue(FlightDataType.TYPE_ALTITUDE, status.getRocketPosition().z);
74                 data.setValue(FlightDataType.TYPE_POSITION_X, status.getRocketPosition().x);
75                 data.setValue(FlightDataType.TYPE_POSITION_Y, status.getRocketPosition().y);
76                 if (extra) {
77                         data.setValue(FlightDataType.TYPE_POSITION_XY,
78                                         MathUtil.hypot(status.getRocketPosition().x, status.getRocketPosition().y));
79                         data.setValue(FlightDataType.TYPE_POSITION_DIRECTION,
80                                         Math.atan2(status.getRocketPosition().y, status.getRocketPosition().x));
81                         
82                         data.setValue(FlightDataType.TYPE_VELOCITY_XY,
83                                         MathUtil.hypot(status.getRocketVelocity().x, status.getRocketVelocity().y));
84                         data.setValue(FlightDataType.TYPE_ACCELERATION_XY,
85                                         MathUtil.hypot(linearAcceleration.x, linearAcceleration.y));
86                         
87                         data.setValue(FlightDataType.TYPE_ACCELERATION_TOTAL, linearAcceleration.length());
88                         
89                         double Re = airSpeed.length() *
90                                         status.getConfiguration().getLength() /
91                                         atmosphere.getKinematicViscosity();
92                         data.setValue(FlightDataType.TYPE_REYNOLDS_NUMBER, Re);
93                 }
94                 
95                 data.setValue(FlightDataType.TYPE_VELOCITY_Z, status.getRocketVelocity().z);
96                 data.setValue(FlightDataType.TYPE_ACCELERATION_Z, linearAcceleration.z);
97                 
98                 data.setValue(FlightDataType.TYPE_VELOCITY_TOTAL, airSpeed.length());
99                 data.setValue(FlightDataType.TYPE_MACH_NUMBER, mach);
100                 
101                 data.setValue(FlightDataType.TYPE_MASS, mass);
102                 
103                 data.setValue(FlightDataType.TYPE_THRUST_FORCE, 0);
104                 data.setValue(FlightDataType.TYPE_DRAG_FORCE, dragForce);
105                 
106                 data.setValue(FlightDataType.TYPE_WIND_VELOCITY, windSpeed.length());
107                 data.setValue(FlightDataType.TYPE_AIR_TEMPERATURE, atmosphere.getTemperature());
108                 data.setValue(FlightDataType.TYPE_AIR_PRESSURE, atmosphere.getPressure());
109                 data.setValue(FlightDataType.TYPE_SPEED_OF_SOUND, atmosphere.getMachSpeed());
110                 
111                 data.setValue(FlightDataType.TYPE_TIME_STEP, timeStep);
112                 data.setValue(FlightDataType.TYPE_COMPUTATION_TIME,
113                                 (System.nanoTime() - status.getSimulationStartWallTime()) / 1000000000.0);
114         }
115         
116 }