Exemple #1
0
    def iterate_lte_ne_eq_pops(self, atmos: Atmosphere):
        atmos.nondimensionalise()
        maxIter = 500
        prevNe = np.copy(atmos.ne)
        ne = np.copy(atmos.ne)
        for it in range(maxIter):
            atomicPops = []
            prevNe[:] = ne
            ne.fill(0.0)
            for a in sorted(self.atoms, key=atomic_weight_sort):
                nTotal = self.atomicTable[a.name].abundance * atmos.nHTot
                nStar = lte_pops(a, atmos, nTotal, debye=True)
                atomicPops.append(AtomicState(a, nStar, nTotal))
                stages = np.array([l.stage for l in a.levels])
                # print(stages)
                ne += np.sum(nStar * stages[:, None], axis=0)
                # print(ne)
            atmos.ne[:] = ne

            relDiff = np.nanmax(np.abs(1.0 - prevNe / ne))
            print(relDiff)
            maxRelDiff = np.nanmax(relDiff)
            if maxRelDiff < 1e-3:
                print("Iterate LTE: %d iterations" % it)
                break
        else:
            print("LTE ne failed to converge")

        atmos.dimensionalise()
        table = AtomicStateTable(atmos, self.atomicTable, atomicPops)
        return table
Exemple #2
0
class Scene2D:
    """Class of the simple 2-dimensional math model of the action world."""
    def __init__(self, xml_rocket: str, xml_traj: str):
        """
        :param xml_rocket: rocket's XML data file's path
        :param xml_traj: trajectory's XML data file's path
        """
        self.atmo = Atmosphere()
        self.rocket = data_read_write.create_rocket(self.atmo, xml_rocket, xml_traj)
        self.is_rocket_calc = False

    # Public
    def sim(self, xml_optim=None):
        """
        Starts the simulation.
        :param xml_optim: optimizer's XML data file's path
        :type xml_optim: str
        """
        if xml_optim is not None:
            optim = self.rocket.optimize_traj(data_read_write.init_optim_range(xml_optim))
            data_read_write.write_optim(optim)
        results = self.rocket.start()
        data_read_write.write_results2d(results)
        self.is_rocket_calc = True

    def show_atmosphere(self):
        """Shows atmosphere's parameters graphs."""
        self.atmo.show()

    def show_rocket_results(self):
        if self.is_rocket_calc is True:
            self.rocket.show_results()
        else:
            print("Warning: the rocket wasn't been calculated!")
    def load_data(self, param_file):
        with open(param_file, 'r') as inputf:
            self.parameters = json.load(inputf)

        # Set imported parameters as properties
        for parameter in self.parameters:
            setattr(self, parameter, self.parameters[parameter])
        # use for threadsafe commnications with the GUI thread
        self.mutex = QMutex()

        self.atmosphere = Atmosphere()

        # TODO Error analysis vs. ticksize
        self.ticksize = 0.001

        self.time = 0
        self.height = self.launch_height
        self.velocity = 0
        self.acceleration = 0

        self.max_height = 0
        self.max_velocity = 0
        self.max_acceleration = 0

        self.mass = self.launch_mass

        self.thruster = Thruster()
        self.data = {}
        self.data['time'] = []
        self.data['height'] = []
        self.data['velocity'] = []
        self.data['acceleration'] = []
Exemple #4
0
 def __init__(self, xml_rocket: str, xml_traj: str):
     """
     :param xml_rocket: rocket's XML data file's path
     :param xml_traj: trajectory's XML data file's path
     """
     self.atmo = Atmosphere()
     self.rocket = data_read_write.create_rocket(self.atmo, xml_rocket, xml_traj)
     self.is_rocket_calc = False
Exemple #5
0
 def update_nTotal(self, atmos : Atmosphere):
     dim = False
     if atmos.dimensioned:
         dim = True
         atmos.nondimensionalise()
     self.nTotal[:] = self.model.atomicTable[self.name].abundance * atmos.nHTot
     if dim:
         atmos.dimensionalise()
Exemple #6
0
    def compute_eq_pops(self, atmos: Atmosphere):
        dim = False
        if atmos.dimensioned:
            dim = True
            atmos.nondimensionalise()
        atomicPops = []
        for a in sorted(self.atoms, key=atomic_weight_sort):
            nTotal = self.atomicTable[a.name].abundance * atmos.nHTot
            nStar = lte_pops(a, atmos, nTotal, debye=True)
            atomicPops.append(AtomicState(a, nStar, nTotal))

        table = AtomicStateTable(atmos, self.atomicTable, atomicPops)
        if dim:
            atmos.dimensionalise
        return table
Exemple #7
0
    def setup(self):
        nn = self.options["num_nodes"]

        self.add_subsystem("atmosphere", subsys=Atmosphere(num_nodes=nn), promotes_inputs=["h"], promotes_outputs=["rho"])
        self.add_subsystem("aerodynamics", subsys=Aerodynamics(num_nodes=nn), promotes_inputs=["alpha", "v", "rho"], promotes_outputs=["lift", "drag"])
        self.add_subsystem("heating", subsys=AerodynamicHeating(num_nodes=nn), promotes_inputs=["rho", "v", "alpha"], promotes_outputs=["q"])
        self.add_subsystem("eom", subsys=FlightDynamics(num_nodes=nn), promotes_inputs=["beta", "gamma", "h", "psi", "theta", "v", "lift", "drag"], promotes_outputs=["hdot", "gammadot", "phidot", "psidot", "thetadot", "vdot"])
Exemple #8
0
    def test_sea_level(self):
        """Test Sea Level properties
        """

        h = 0
        a1 = Atmosphere(h)

        self.assertAlmostEqual(a1.T, 273 + 15, places=0)
        self.assertAlmostEqual(a1.P, 101325, places=0)
        self.assertAlmostEqual(a1.rho, 1.225, places=4)
Exemple #9
0
def get_pv(forcing, output, n1=0, n2=10000, option="timeseries"):
    """ forcing : nc file assumed to be located in Forcings/ e.g. "SIRTA_all" 
        output : name of output file containing PV production, stored in PV_Outputs directory       
        n1 and n2 : left and right indicess for partial computations along timeseries
        option : specify the type of forcing to optimize vectorial computations
    """
    print("----------Namelist loading----------------")
    nam = Namelist(
    )  # all options should be hardcoded in the Namelist() attributes

    print("----------Atmosphere loading----------------")
    # build an Atmosphere object from an nc file. Such object can be built directly from np.arrays
    atm = Atmosphere(*tools.get_atm_from_ncfile(
        forcing=forcing, albedo=nam.albedo, n1=n1, n2=n2))
    atm.compute_sun()  # to compute the full series of sza, saa, sw_toa

    # define PV panel from information contained in Namelist
    print("----------Module initialization----------------")
    panel = Panel(
        name=nam.panel_name,
        technology=nam.panel_technology,
        beta=nam.panel_beta,
        gamma=nam.panel_gamma,
        method_FF=nam.method_FF,
        SR_method=nam.SR_method,
        namelist=nam
    )  # get physical characteristics of the panel from a description file - here SIRTA panel used for consistency

    # call pv_interface to handle large arrays and successive (and possibly multi-thread) calls to pv_production
    t1 = time.time()
    if option == "timeseries":
        power_simul = pv_interface_timeseries(nam, atm, panel)
    elif option == "atlas":
        power_simul = pv_interface_atlas(nam, atm, panel)

    # save PV outputs
    np.savetxt("PV_Outputs/%s.dat" % output, power_simul)
    t2 = time.time()
    print("Time to run the PV code = %s seconds" % (t2 - t1))

    return atm.dates, power_simul, atm.lat, atm.lon
Exemple #10
0
    def test_under_86km(self):
        """Tests for altitude values between 35 and 86 km
        """

        z = np.array([50000.0, 70000.0, 86000.0])
        expected_T = np.array([270.65, 219.585, 186.87])
        expected_p = np.array([79.779, 5.2209, 0.37338])
        expected_rho = np.array([0.0010269, 0.000082829, 0.000006958])

        for idx, z_current in enumerate(z):
            a = Atmosphere(z_current)

            self.assertAlmostEqual(a.T, expected_T[idx], places=0)
            self.assertAlmostEqual(a.P, expected_p[idx], places=-2)
            self.assertAlmostEqual(a.rho, expected_rho[idx], places=4)
Exemple #11
0
    def test_under_35km(self):
        """Tests for altitude values between 11 and 35 km
        """

        z = np.array([15000.0, 25000.0, 35000.0])
        expected_T = np.array([216.65, 221.552, 236.513])
        expected_p = np.array([12111.0, 2549.2, 574.59])
        expected_rho = np.array([0.19476, 0.040084, 0.0084634])

        for idx, z_current in enumerate(z):
            a = Atmosphere(z_current)

            self.assertAlmostEqual(a.T, expected_T[idx], places=3)
            self.assertAlmostEqual(a.P, expected_p[idx], places=-2)
            self.assertAlmostEqual(a.rho, expected_rho[idx], places=4)
Exemple #12
0
    def test_under_11km(self):
        """Tests for altitude values between 1 and 11 km
        """

        z = np.array([500.0, 2500.0, 6500.0, 9000.0, 11000.0])

        expected_T = np.array([284.900, 271.906, 245.943, 229.733, 216.774])
        expected_p = np.array([95461.0, 74691.0, 44075.0, 30800.0, 22699.0])
        expected_rho = np.array([1.1673, 0.95695, 0.62431, 0.46706, 0.36480])

        for idx, z_current in enumerate(z):
            a = Atmosphere(z_current)

            self.assertAlmostEqual(a.T, expected_T[idx], places=3)
            self.assertAlmostEqual(a.P, expected_p[idx], places=-2)
            self.assertAlmostEqual(a.rho, expected_rho[idx], places=4)
Exemple #13
0
    def test_under_1000m(self):
        """Tests for altitude values under 1000 meters
        """

        z = np.array([50.0, 550.0, 850.0])

        expected_T = np.array([287.825, 284.575, 282.626])
        expected_p = np.array([100720.0, 94890.0, 91523.0])
        expected_rho = np.array([1.2191, 1.1616, 1.1281])

        for idx, z_current in enumerate(z):
            a = Atmosphere(z_current)

            self.assertAlmostEqual(a.T, expected_T[idx], places=3)
            self.assertAlmostEqual(a.P, expected_p[idx], places=-2)
            self.assertAlmostEqual(a.rho, expected_rho[idx], places=4)
Exemple #14
0
def __main__():
    #initDict = readInit(init_file="SunEarth_4m.init")
    initDict = readInit(init_file="TMT_SuperEarth_N.init")
    wav_min, wav_max, t_exp = np.float32(initDict["wav_min"]), np.float32(
        initDict["wav_max"]), np.float32(initDict["t_exp"])
    target_pl = Target(distance=np.float32(initDict["distance"]),
                       spec_path=initDict["pl_spec_path"],
                       inclination_deg=np.float32(
                           initDict["pl_inclination_deg"]),
                       rotation_vel=np.float32(initDict["pl_rotation_vel"]),
                       radial_vel=np.float32(initDict["pl_radial_vel"]),
                       spec_reso=np.float32(initDict["spec_reso"]))
    target_st = Target(distance=np.float32(initDict["distance"]),
                       spec_path=initDict["st_spec_path"],
                       inclination_deg=np.float32(
                           initDict["st_inclination_deg"]),
                       rotation_vel=np.float32(initDict["st_rotation_vel"]),
                       radial_vel=np.float32(initDict["st_radial_vel"]),
                       spec_reso=np.float32(initDict["spec_reso"]))
    wav_med = (wav_min + wav_max) / 2.0
    if initDict["spec_tran_path"] != "None":
        atmosphere = Atmosphere(spec_tran_path=initDict["spec_tran_path"],
                                spec_radi_path=initDict["spec_radi_path"])
    else:
        atmosphere = None
    instrument = Instrument(
        wav_med,
        telescope_size=np.float32(initDict["telescope_size"]),
        pl_st_contrast=np.float32(initDict["pl_st_contrast"]),
        spec_reso=np.float32(initDict["spec_reso"]),
        read_noise=np.float32(initDict["read_noise"]),
        dark_current=np.float32(initDict["dark_current"]),
        fiber_size=np.float32(initDict["fiber_size"]),
        pixel_sampling=np.float32(initDict["pixel_sampling"]),
        throughput=np.float32(initDict["throughput"]),
        wfc_residual=np.float32(initDict["wfc_residual"]),
        num_surfaces=np.float32(initDict["num_surfaces"]),
        temperature=np.float32(initDict["temperature"]))
    thermal_background = ThermTarget(instrument,
                                     spec_reso=np.float32(
                                         initDict["spec_reso"]))
    zodi = ZodiTarget(instrument,
                      distance=np.float32(initDict["distance"]),
                      spec_path=initDict["zodi_spec_path"],
                      exozodi_level=np.float32(initDict["exozodi_level"]),
                      spec_reso=np.float32(initDict["spec_reso"]))
    hci_hrs = HCI_HRS_Observation(wav_min,
                                  wav_max,
                                  t_exp,
                                  target_pl,
                                  target_st,
                                  instrument,
                                  thermal_background,
                                  zodi,
                                  atmosphere=atmosphere)
    print(
        "Star flux: {0} \nLeaked star flux: {1}\nPlanet flux: {2}\nPlanet flux per pixel: {3}\nThermal background flux:  {4}\nThermal background flux per pixel:  {5}\nSky flux: {6}\nSky flux per pixel: {7}\nSky transmission: {8}\nTotal pixel number: {9}\n"
        .format(
            hci_hrs.star_total_flux,
            hci_hrs.star_total_flux * instrument.pl_st_contrast,
            hci_hrs.planet_total_flux, hci_hrs.planet_total_flux /
            (len(hci_hrs.obs_spec_resample.flux) + 0.0),
            hci_hrs.therm_total_flux, hci_hrs.therm_total_flux /
            (len(hci_hrs.obs_therm_resample.flux) + 0.0),
            hci_hrs.sky_total_flux, hci_hrs.sky_total_flux /
            (len(hci_hrs.obs_therm_resample.flux) + 0.0),
            hci_hrs.sky_transmission, len(hci_hrs.obs_therm_resample.flux)))
    spec = pyfits.open(initDict["template_path"])
    template = Spectrum(spec[1].data["Wavelength"],
                        spec[1].data["Flux"],
                        spec_reso=np.float32(initDict["spec_reso"]))
    if initDict["spec_tran_path"] != "None":
        hci_hrs_red = HCI_HRS_Reduction(hci_hrs,
                                        template,
                                        save_flag=False,
                                        obj_tag=initDict["obj_tag"],
                                        template_tag=initDict["template_tag"],
                                        speckle_flag=False)
    else:
        hci_hrs_red = HCI_HRS_Reduction(hci_hrs,
                                        template,
                                        save_flag=False,
                                        obj_tag=initDict["obj_tag"],
                                        template_tag=initDict["template_tag"],
                                        speckle_flag=True)
import numpy as np

from aircraft import Aircraft
from atmosphere import Atmosphere, Wind
from constants import Constants
import sim_setup

from Planes.B737 import B737
from Planes.C172 import C172
from Planes.T38 import T38

# Initialization of objects used in overall sim architecture
SIM = sim_setup.Sim_Parameters()
CONSTANTS = Constants()
Atmosphere = Atmosphere()
plane1 = Aircraft()

####################################################################################################
# BEGIN INPUT FIELDS
####################################################################################################

# Modify simulation parameters
SIM.START_TIME = 0.0
SIM.END_TIME = 2000.0
SIM.DELTA_T = 2

# Modify aircraft inital conditions

# Choose airplane type - B737, C172, T38
plane1.design = B737()
Exemple #16
0
CD = 0.5  # Approximate drag coefficient of vehicle
AREA = 0.79  # Frontal area of rocket
GRAV = 32.174
DENSITY = 0.0765  # constant for simplicity for now
MASS = 1.24324  # lbs
TIME = 0
STEP = 0.01


def acceleration(velocity, density, input):
    cd = CD + (0.75 * input)
    return -GRAV - (cd * AREA * density * (velocity**2) / (2 * MASS))


AtmosEngine = Atmosphere()
altitude = 1000
velocity = 700
accel = acceleration(velocity, AtmosEngine.density(altitude), 0)

pid = PID(0.00025, 0.001, 0.1, 3500, 0, 1)

pid_outputs = []

while velocity > 0:
    altitude += velocity * STEP
    velocity += accel * STEP
    p_alt = projected_altitude(accel, velocity, altitude)
    pid_output = pid.output(p_alt, STEP)
    accel = acceleration(velocity, AtmosEngine.density(altitude), pid_output)
    pid_outputs.append(pid_output)
Exemple #17
0
    """Recreate Fig. 14.4 & 14.5 from Anderson Hypersonic & High Temperature Gas Dynamics
    """

    altitudes = np.array([35900, 59800, 82200, 100000, 120300, 154800, 173500,
                          200100, 230400, 259700, 294800, 322900]) * ft_to_m

    fig1, ax1 = plt.subplots(figsize=(12, 9))
    fig2, ax2 = plt.subplots(figsize=(12, 9))

    T1 = 225.0

    # Convert altitudes into ambient pressures
    pressures = np.zeros_like(altitudes)
    for idx, altitude in enumerate(altitudes):
        a = Atmosphere(altitude)
        pressures[idx] = a.P

    u1 = np.linspace(4000, 40000, num=75) * ft_to_m

    # Calculate shock properties for each pressure
    for pidx, p1 in enumerate(pressures):
        T2_arr = np.zeros_like(u1)
        rho2_rho1_arr = np.zeros_like(u1)

        for uidx, u in enumerate(u1):

            results = normal_shock(air, u, T1, p1)
            if not results:
                continue
class RocketSimulator(QtCore.QObject):
    R_EARTH = 6371000 # meters
    G_0 = -9.80665 # m/s^2 (at sea level)

    new_data  = QtCore.pyqtSignal(object)


    def __init__(self, ticksize, param_file='parameters.json'):
        QtCore.QObject.__init__(self)
        self.load_data(param_file)


    def load_data(self, param_file):
        with open(param_file, 'r') as inputf:
            self.parameters = json.load(inputf)

        # Set imported parameters as properties
        for parameter in self.parameters:
            setattr(self, parameter, self.parameters[parameter])
        # use for threadsafe commnications with the GUI thread
        self.mutex = QMutex()

        self.atmosphere = Atmosphere()

        # TODO Error analysis vs. ticksize
        self.ticksize = 0.001

        self.time = 0
        self.height = self.launch_height
        self.velocity = 0
        self.acceleration = 0

        self.max_height = 0
        self.max_velocity = 0
        self.max_acceleration = 0

        self.mass = self.launch_mass

        self.thruster = Thruster()
        self.data = {}
        self.data['time'] = []
        self.data['height'] = []
        self.data['velocity'] = []
        self.data['acceleration'] = []


    def run_simulation(self):

        while self.height >= self.launch_height:
            self.run_tick()
        print(self.max_height, self.max_velocity, self.max_acceleration)

    def run_tick(self):

        self.height += self.velocity * self.ticksize
        self.velocity += self.acceleration * self.ticksize

        force = self.thrust_force() + self.drag_force() + self.gravity_force()
        self.acceleration = force / self.mass

        locked = False
        if self.mutex.tryLock(10):

            self.new_data.emit([self.time, self.height, self.velocity, self.acceleration])
            self.mutex.unlock()

        self.data['time'].append(self.time)
        self.data['height'].append(self.height)
        self.data['velocity'].append(self.velocity)
        self.data['acceleration'].append(self.acceleration)

        self.update_mass()
        self.update_max_values()
        self.time += self.ticksize

    def drag_force(self):
        pressure = self.atmosphere.get_density_by_height(self.height)
        # Rocket is heading up
        if self.velocity >= 0:
            drag_coef = self.rocket_drag_coef
            area = self.cross_sectional_area
        # Rocket is falling with parachute deployed
        else:
            drag_coef = self.parachute_drag_coef
            area = self.parachute_area

        # Drag force is the opposite direction of velocity
        if self.velocity > 0:
            direction = -1
        else:
             direction = 1

        # TODO use increased parachute area
        return (direction * drag_coef * pressure * self.velocity**2 * area ) / 2


    def gravity_force(self):
        return self.mass * self.get_g_at_alitude(self.height)

    def get_g_at_alitude(self, height):
        return self.G_0 * ((height + self.R_EARTH) / self.R_EARTH)**2


    def thrust_force(self):
        if self.time < self.burn_length:
            return self.thruster.get_thrust_at_time(self.time)
        else:
            return 0

    def update_mass(self):
        if self.time > self.burn_length:
            return
        else:
            self.mass -= (self.propellent_mass / self.burn_length) * self.ticksize

    def update_max_values(self):
        if self.height > self.max_height:
            self.max_height = self.height

        if self.velocity > self.max_velocity:
            self.max_velocity = self.velocity

        if self.acceleration > self.max_acceleration:
            self.max_acceleration = self.acceleration
Exemple #19
0
def main():
    # Initial setup
    pygame.init()
    running = True
    clock = pygame.time.Clock()
    tick_time = 30

    # Screen size and screen object creation
    screen_size = (1920, 1080)
    # screen = pygame.display.set_mode(screen_size)
    screen = pygame.display.set_mode(screen_size, pygame.FULLSCREEN)

    # Window title and icon
    pygame.display.set_caption("SPACE")
    pygame.display.set_icon(pygame.image.load("assets/img/ship.png"))

    # Background color
    bg = (0, 0, 0)

    # Set font for text
    font = pygame.font.SysFont('consolas', 16)

    # Initialize the actors
    # Ship initial conditions
    # Default spawn point is defined in ship class
    ship_img_path = "assets/img/ship.png"
    ship_spawn = (25, 75)
    ship_size = (20, 15)
    ship = Ship(ship_spawn, ship_img_path, ship_size)

    # Planet initial conditions
    planet_spawn = (500, 375)
    planet_img_path = "assets/img/moon1.png"
    planet_mass = 8e10
    planet_size = (50, 50)
    planet_influence_height = 250
    planet_radius_offset = 1.3  # used below for fine tuning planet collision detection
    planet = Planet(planet_spawn, planet_img_path, planet_size, planet_mass,
                    planet_influence_height)

    # Atmosphere initial conditions
    atm_spawn = (planet_spawn[0] - planet_size[0] / 2,
                 planet_spawn[1] - planet_size[1] / 2)
    atm_img_path = "assets/img/atm.png"
    atm_size = (100, 100)
    atm_press = .002
    atm = Atmosphere(atm_spawn, atm_img_path, atm_size, atm_press)

    min_orbit_radius = 180
    min_orbit = pygame.Rect(
        tuple([
            planet.get_center()[0] - min_orbit_radius,
            planet.get_center()[1] - min_orbit_radius
        ]), tuple([min_orbit_radius * 2, min_orbit_radius * 2]))

    max_orbit_radius = 200
    max_orbit = pygame.Rect(
        tuple([
            planet.get_center()[0] - max_orbit_radius,
            planet.get_center()[1] - max_orbit_radius
        ]), tuple([max_orbit_radius * 2, max_orbit_radius * 2]))

    success_orbit_padding = 4
    success_orbit_radius = max_orbit_radius - (success_orbit_padding // 2)
    success_orbit_thickness = max_orbit_radius - min_orbit_radius - success_orbit_padding
    success_orbit = pygame.Rect(
        tuple([
            planet.get_center()[0] - success_orbit_radius,
            planet.get_center()[1] - success_orbit_radius
        ]), tuple([success_orbit_radius * 2, success_orbit_radius * 2]))

    while running:
        # Paint screen background
        screen.fill(bg)

        # Get events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

            tick_time = get_keystrokes(event, ship)

        # Set collision boundaries with walls
        ship.set_wall_collision(screen_size)

        # Set collision boundaries with planet
        ship.set_body_collision(planet, planet_radius_offset)

        # Gravitational attraction
        planet.attract_body(ship)

        # Update atmospheric drag deceleration on ship
        atm.update_drag(ship)

        # Update ship velocity and position
        ship.update_velocity()
        ship.update_position()
        ship.check_fuel()

        # Text objects here:
        # Fuel display text object
        fuel_display_string = "Fuel:"
        fuel_display_loc = (10, 10)
        fuel_display = font.render(fuel_display_string, True, (0, 255, 0))

        score = 0
        if min_orbit_radius <= ship.get_apoapsis(planet) <= max_orbit_radius:
            score = int(50 / ship.get_eccentricity(planet))
            if min_orbit_radius <= ship.get_periapsis(
                    planet) <= max_orbit_radius:
                pygame.draw.ellipse(screen, (0, 63, 0), success_orbit,
                                    success_orbit_thickness)

        # Debug Text
        debug_display_string = "Score: " + str(score) + " xAccel: " + str(
            ship.thrust_x) + " yAccel: " + str(ship.thrust_y)
        debug_display_loc = (10, 120)
        debug_display = font.render(debug_display_string, True, (0, 255, 0))

        # Update ship trail points
        if ship.get_distance_from_point(
                ship.trail_points[-1]) >= ship.trail_res:
            ship.trail_points.append(ship.get_center())
        # Trim the ship trail length if it gets too long
        if len(ship.trail_points) > ship.trail_len:
            ship.trail_points.pop(0)

        # Draw a trailing line from the ship
        if len(ship.trail_points) > 1 and ship.get_apoapsis(
                planet) <= planet_influence_height:
            pygame.draw.lines(screen, (0, 127, 0), False, ship.trail_points)

        pygame.draw.ellipse(screen, (127, 127, 0), min_orbit, width=1)
        pygame.draw.ellipse(screen, (127, 127, 0), max_orbit, width=1)

        # Blit sprites to screen
        ship.blit_sprite(screen)
        atm.blit_sprite(screen)
        planet.blit_sprite(screen)

        fuel_bar_width = 100
        fuel_bar_height = 15
        fuel_bar_dyn_width = fuel_bar_width * ship.fuel / 100.0
        # Avoiding left-side fuel_bar bleed when fuel value is less than 1.0
        if ship.fuel <= 1.0:
            fuel_bar_dyn_width = 1
        fuel_bar_container = pygame.Rect((10, 30),
                                         (fuel_bar_width, fuel_bar_height))
        fuel_bar = pygame.Rect((10, 30), (fuel_bar_dyn_width, fuel_bar_height))

        # Blit text
        screen.blit(fuel_display, fuel_display_loc)
        screen.blit(debug_display, debug_display_loc)

        # Dynamic fuel bar color (Default: Green; Half-fuel: Yellow; Low-Fuel: Red)
        fuel_bar_color = (0, 255, 0)
        if 50.0 > ship.fuel >= 10.0:
            fuel_bar_color = (255, 255, 0)
        elif ship.fuel < 10.0:
            fuel_bar_color = (255, 0, 0)

        # Draw fuel bars
        pygame.draw.rect(screen, (127, 127, 127), fuel_bar_container)
        # Fuel bar disappears if fuel is depleted
        if ship.fuel != 0.0:
            pygame.draw.rect(screen, fuel_bar_color, fuel_bar)

        clock.tick(tick_time)

        # Update screen at end of loop
        pygame.display.update()
Exemple #20
0
    def __init__(self,Nmax,Xmax,X0=-150,Lambda=70,
                 zenith=0,azimuth=0,impact_x=0,impact_y=0,
                 ckarray='gg_t_delta_theta.npz'):
        """Create a shower with the given Gaisser-Hillas parameters and
        geometry
        
        Parameters:
            Nmax: the maximum size of the shower
            Xmax: the slant depth a maximum of the shower
            X0: the "starting point depth" for the shower
            Lambda: the growth rate of the shower
            zenith: the zenith angle of the shower
            azimuth: the azimuthal angle of the shower
            ckarray: the name of the file containing the CherenkovPhotonArray
        """
        self.Nmax   = Nmax
        self.Xmax   = Xmax
        self.X0     = X0
        self.Lambda = Lambda
        self.zenith = zenith
        self.azimuth = azimuth
        self.impact_x = impact_x
        self.impact_y = impact_y

        self.atmosphere = Atmosphere()
        self.ng_t_delta_Omega = CherenkovPhotonArray(ckarray)

        cq = np.cos(zenith)
        sq = np.sin(zenith)
        cp = np.cos(azimuth)
        sp = np.sin(azimuth)
        
        steps = np.append(
            np.append(
                np.linspace(   0, 1000,100,endpoint=False,dtype=float),
                np.linspace(1000,10000,90,endpoint=False,dtype=float)),
            np.linspace(10000,84000,75,dtype=float))
        hs  = (steps[1:]+steps[:-1])/2
        dhs = steps[1:]-steps[:-1]
        nh = len(hs)
        rs = hs*sq/cq

        c = value('speed of light in vacuum')
        
        xs = np.empty_like(hs)
        xs[-1] = self.atmosphere.depth(hs[-1])
        for i in range(nh-2,-1,-1):
            xs[i] = xs[i+1] + self.atmosphere.depth(hs[i],hs[i+1])
        xs /= cq

        self.location = np.empty((nh,3),dtype=float)
        self.location[:,0] = self.impact_x + rs*cp
        self.location[:,1] = self.impact_y + rs*sp
        self.location[:,2] = hs
        self.heights = self.location[:,2]
        self.steps = dhs/cq
        self.times = hs/cq/c
        self.slant_depths = xs
        self.sizes = self.size(xs)
        self.stages = self.stage(xs)
        self.deltas = self.atmosphere.delta(hs)
        xh = zip(xs,hs)
        self.csizes = np.array([self.cherenkov_size(x,h) for x,h in xh])
        xh = zip(xs,hs)
        self.cyield = np.array([self.cherenkov_yield(x,h) for x,h in xh])
        self.cphots = self.steps * self.csizes * self.cyield
        nq = len(self.ng_t_delta_Omega.theta)
        self.cangs = np.empty((nh,nq),dtype=float)
        itd = zip(np.arange(nh),self.stages,self.deltas)
        for i,t,d in itd:
            self.cangs[i] = self.ng_t_delta_Omega.angular_distribution(t,d)
Exemple #21
0
class ShowerCherenkov():
    """A class to contain a instance of a shower with a Gaisser-Hillas
    parameterization, a given geometry, an atmosphere, and a table of 
    Cherenkov photon angular distributions. An instance of this class
    will allow one to calculate the Cherenkov photon flux at a given
    point on the ground (or at some altitude) and the time distribution
    of those photons.
    """

    def __init__(self,Nmax,Xmax,X0=-150,Lambda=70,
                 zenith=0,azimuth=0,impact_x=0,impact_y=0,
                 ckarray='gg_t_delta_theta.npz'):
        """Create a shower with the given Gaisser-Hillas parameters and
        geometry
        
        Parameters:
            Nmax: the maximum size of the shower
            Xmax: the slant depth a maximum of the shower
            X0: the "starting point depth" for the shower
            Lambda: the growth rate of the shower
            zenith: the zenith angle of the shower
            azimuth: the azimuthal angle of the shower
            ckarray: the name of the file containing the CherenkovPhotonArray
        """
        self.Nmax   = Nmax
        self.Xmax   = Xmax
        self.X0     = X0
        self.Lambda = Lambda
        self.zenith = zenith
        self.azimuth = azimuth
        self.impact_x = impact_x
        self.impact_y = impact_y

        self.atmosphere = Atmosphere()
        self.ng_t_delta_Omega = CherenkovPhotonArray(ckarray)

        cq = np.cos(zenith)
        sq = np.sin(zenith)
        cp = np.cos(azimuth)
        sp = np.sin(azimuth)
        
        steps = np.append(
            np.append(
                np.linspace(   0, 1000,100,endpoint=False,dtype=float),
                np.linspace(1000,10000,90,endpoint=False,dtype=float)),
            np.linspace(10000,84000,75,dtype=float))
        hs  = (steps[1:]+steps[:-1])/2
        dhs = steps[1:]-steps[:-1]
        nh = len(hs)
        rs = hs*sq/cq

        c = value('speed of light in vacuum')
        
        xs = np.empty_like(hs)
        xs[-1] = self.atmosphere.depth(hs[-1])
        for i in range(nh-2,-1,-1):
            xs[i] = xs[i+1] + self.atmosphere.depth(hs[i],hs[i+1])
        xs /= cq

        self.location = np.empty((nh,3),dtype=float)
        self.location[:,0] = self.impact_x + rs*cp
        self.location[:,1] = self.impact_y + rs*sp
        self.location[:,2] = hs
        self.heights = self.location[:,2]
        self.steps = dhs/cq
        self.times = hs/cq/c
        self.slant_depths = xs
        self.sizes = self.size(xs)
        self.stages = self.stage(xs)
        self.deltas = self.atmosphere.delta(hs)
        xh = zip(xs,hs)
        self.csizes = np.array([self.cherenkov_size(x,h) for x,h in xh])
        xh = zip(xs,hs)
        self.cyield = np.array([self.cherenkov_yield(x,h) for x,h in xh])
        self.cphots = self.steps * self.csizes * self.cyield
        nq = len(self.ng_t_delta_Omega.theta)
        self.cangs = np.empty((nh,nq),dtype=float)
        itd = zip(np.arange(nh),self.stages,self.deltas)
        for i,t,d in itd:
            self.cangs[i] = self.ng_t_delta_Omega.angular_distribution(t,d)
        
    def __repr__(self):
        return "ShowerCherernkov(%.2e,%.0f,%.0f,%.0f,%.4f)"%(
            self.Nmax,self.Xmax,self.X0,self.Lambda,self.zenith)

    def size(self,X):
        """Return the size of the shower at a slant-depth X

        Parameters:
            X: the slant depth at which to calculate the shower size [g/cm2]

        Returns:
            N: the shower size
        """
        x =         (X-self.X0)/self.Lambda
        m = (self.Xmax-self.X0)/self.Lambda
        n = np.exp( m*(np.log(x)-np.log(m)) - (x-m) )
        return self.Nmax * n
    
    def size_height(self,h):
        """Return the size of the shower at an elevation h

        Parameters:
            h: the height about sea-level [m]

        Returns:
            N: the shower size
        """
        d1 = h/np.cos(self.zenith)
        X = self.atmosphere.depth(d1) if self.zenith==0 else \
            self.atmosphere.slant_depth(self.zenith,d1)
        return self.size(X)

    def stage(self,X,X0=36.62):
        """Return the shower stage at a given slant-depth X. This
        is after Lafebre et al.
        
        Parameters:
            X: atmosphering slant-depth [g/cm2]
            X0: radiation length of air [g/cm2]

        Returns:
            t: shower stage
        """
        return (X-self.Xmax)/X0
    
    def cherenkov_size(self,X,h):
        """Return the size of the shower at a given slant-depth X
        that can produce Cherenkov radiation.

        Parameters:
            X: the slant depth at which to calculate the shower size [g/cm2]
            h: the height corresponding to the X [m]

        Returns:
            N: the size of the shower over the Cherenkov threshold
        """
        delta = self.atmosphere.delta(h)
        Ec = CherenkovPhoton.cherenkov_threshold(delta)
        t = self.stage(X)
        fe = EnergyDistribution('Tot',t)
        fraction,_ = quad(fe.spectrum,np.log(Ec),35.)
        return fraction*self.size(X)

    def cherenkov_yield(self,X,h,lambda1=300.,lambda2=600.):
        """Return the number of Cherenkov photons produced at X and h.

        Parameters:
            X: the slant depth at which to calculate the Cherenkov yield [g/cm2]
            h: the height corresponding to the X [m]
            lambda1: the lower limit to the wavelength range [nm]
            lambda2: the upper limit to the wavelength range [nm]

        Returns:
            Nck: the Number of Cherenkov photons produced [1/m]

        
        """
        alpha_over_hbarc = 370.e2 # per eV per m, from PDG
        hc = value('Planck constant in eV s') * \
             value('speed of light in vacuum')
        E1 = hc/(lambda1*nano)
        E2 = hc/(lambda2*nano)
        dE = np.abs(E1-E2)
        delta = self.atmosphere.delta(h)
        q = CherenkovPhoton.cherenkov_angle(1.e12,delta)
        return alpha_over_hbarc * np.sin(q)**2 * dE
Exemple #22
0
def pv_interface_timeseries(namelist, atm, panel):
    """Return the spatio-temporal PV power from atmospheric inputs, panel characteristics and PV code options"""

    ncol, nt = np.shape(atm.ta)  # to get the dimensions of the input
    nthread = namelist.nthread  # number of parallel processes
    power = []  # initialization of the power to be returned

    for n in range(ncol):
        # The code is called for each point of the domain, and a time series is returned
        atm_column = Atmosphere(
            *atm.get_column(n))  # extract one column from full atmosphere
        atm_column.set_sun_geometry(
            atm.sza[n, :], atm.saa[n, :], atm.sw_toa[n, :]
        )  # sun geometry for the point is taken from full sun geometry

        if panel.technology == "tracker":
            panel.set_geometry(atm_column.sza, atm_column.saa, atm_column)  #

        # Multi-porcessing
        if nthread > 1:
            #----------------------------
            import multiprocessing as mp
            #----------------------------
            print("Multi-processes with %s processes" % nthread)

            outputs = [
                mp.Queue() for x in range(nthread)
            ]  # independent Queue objects to avoid out-of-order return at the end
            m = int(nt // nthread)  # how to equally slice the input atmosphere
            processes = []
            # Preparing all processes
            for k in range(nthread - 1):
                n1 = k * m  # start of the slice
                n2 = (k + 1) * m  # end of the slice
                atm_temp = Atmosphere(*atm_column.get_column_time_series(
                    n1, n2
                ))  # new atmosphere built as temporal slice of full atmosphere
                atm_temp.set_sun_geometry(
                    atm_column.sza[n1:n2], atm_column.saa[n1:n2],
                    atm_column.sw_toa[n1:n2]
                )  # sun geometry set for this Atmosphere object
                processes += [
                    mp.Process(target=pv_prod,
                               args=(namelist, atm_temp, panel, n2 - n1,
                                     outputs[k]))
                ]  # processes call pv_production vi pv_prod interface and output the result to the dedicated Queue

            # Residual for last thread
            n1 = (nthread - 1) * m
            n2 = nt
            atm_temp = Atmosphere(*atm_column.get_column_time_series(n1, n2))
            atm_temp.set_sun_geometry(atm_column.sza[n1:n2],
                                      atm_column.saa[n1:n2],
                                      atm_column.sw_toa[n1:n2])
            processes += [
                mp.Process(target=pv_prod,
                           args=(namelist, atm_temp, panel, n2 - n1,
                                 outputs[-1]))
            ]

            # Start processes
            for p in processes:
                p.start()

            # Exit the completed processes
            for p in processes:
                p.join()

            # Concatenate all Queues
            power0 = np.array([])
            for k, p in enumerate(processes):
                power0 = np.concatenate((power0, outputs[k].get()))

        # No multi-processing but splitting input according to maxcol if provided
        else:
            try:
                mt = namelist.maxlen  # split full timeseries into slices of length maxlen
                m = int(
                    nt // mt
                )  # this corresponds to m + 1 independent computations (nt = m * mt + res)
                power0 = np.array([])
                print("Time series split in", m)
                for k in range(m):
                    n1 = k * mt  # start of the slice
                    n2 = (k + 1) * mt  # end of the slice
                    atm_temp = Atmosphere(
                        *atm_column.get_column_time_series(n1, n2)
                    )  # new atmosphere built as temporal slice of full atmosphere
                    atm_temp.set_sun_geometry(
                        atm_column.sza[n1:n2], atm_column.saa[n1:n2],
                        atm_column.sw_toa[n1:n2]
                    )  # sun geometry set for this Atmosphere object
                    power0 = np.concatenate(
                        (power0, pv_power(namelist, atm_temp, panel, n2 - n1)))

                # Residual for last thread
                n1 = m * mt
                n2 = nt
                atm_temp = Atmosphere(
                    *atm_column.get_column_time_series(n1, n2))
                atm_temp.set_sun_geometry(atm_column.sza[n1:n2],
                                          atm_column.saa[n1:n2],
                                          atm_column.sw_toa[n1:n2])
                power0 = np.concatenate(
                    (power0, pv_power(namelist, atm_temp, panel, n2 - n1)))

            except:
                power0 = pv_power(namelist, atm_column, panel, nt)

        power += [power0]

    return np.array(power)