appl121105_iotorus.simulatorΒΆ

'''Simulator class

.. todo::

    Io phase setting method.

.. todo::

    Future, but plasma model not in the JEqS frame.
'''
import logging
logging.basicConfig()

import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate

from . import neutralmodel
from . import plasmamodel
from . import xsect
from . import trajectory
from . import jupiter
from . import moon_io
from . import f2j

import pyana.pep.iotorus



class SimulatorCore:
    logger = logging.getLogger('SimulatorCore')
    #logger.setLevel(logging.DEBUG)
    def __init__(self):
        self.observer = None
        self.trajectory = None

        self.tlist = None

        self.enamass = 16.

        tpm = pyana.pep.iotorus.TwoPeakModel()
        self.nmodel = neutralmodel.NeutralModelTwoPeak2(moon_io.Io())
#        self.pmodel = plasmamodel.SimpleCorotationalFlow2(m_amu=self.enamass)
        self.pmodel = plasmamodel.CorotationalFlowMJconv(m_amu=self.enamass)
        self.xsectmodel = xsect.CrossSectionSimplest()

    def set_iophase(self, iophase):
        ''' Set the io phase.
        '''
        self.nmodel = neutralmodel.NeutralModelTwoPeak2(moon_io.Io(initial_phase_degree=iophase))

    def set_jupiterphase(self, jupiter_phase):
        self.pmodel = plasmamodel.CorotationalFlowMJconv(m_amu=self.enamass, jupiter_phase=jupiter.JupiterPhase(jupiter_phase))

    def set_observer(self, observer):
        ''' Set the observer.
        ''' 
        self.observer = observer
        self.trajectory = trajectory.Trajectory(self.observer)

    def set_tlist(self, tlist):
        ''' Set the calculation time list
        '''
        self.tlist = tlist

    def run(self, mpl=False, debug=False, mpl_prefix=None):
        ''' Run the calculation.
        '''
        if self.observer == None:
            raise ValueError('!!! Observer not defined.\n'
                '     Use set_observer method\n'
                '     to set the observer.\n')

        if self.tlist == None:
            raise ValueError('!!! Time list not defined.\n'
                '     Use set_tlist method\n'
                '     to set the Time list.\n')

        nt = len(self.tlist)
        # First, trajectory is calculated.
        dist_along, traj_coord = self.trajectory.get_length(self.tlist)  # (3, N), km
        velvecs = traj_coord[3:, :]
        traj_coord = traj_coord[:3, :]
        # Then, calculate the neutral density there.
        # Then, also calculate the plasma distribution function there.
        neutral_alongtraj = self.nmodel.get_density(traj_coord[0, :],
                            traj_coord[1, :], traj_coord[2, :], tarr=self.tlist)
        plasma_distfunc = self.pmodel.get_distribution_function(
                            traj_coord[0, :], traj_coord[1, :],
                            traj_coord[2, :],
                            velvecs[0, :], velvecs[1, :], velvecs[2, :], tarr=self.tlist)
        crosssection = np.zeros([nt])
        for i_t in range(nt):
            # For generic purpose, argument should be |vp-vn|
            crosssection[i_t] = self.xsectmodel.get_crosssection()

        ### ENA distribution function, df/dl, in MKSA.  s3/m6 * /m3 * m2
        denaflux = plasma_distfunc * (neutral_alongtraj * 1e6) * (crosssection / 1e4)
        ### Integral over L.  f.
        dist_along_meter = dist_along * 1e3  # in m

        ### Integral
        f_ENA = scipy.integrate.trapz(denaflux, x=dist_along_meter)

        if debug:  # Too power hungry.  Only for debugging.
            self.logger.debug('xyz [km] = %g %g %g' % str(traj_coord))
            self.logger.debug('vxyz [km/s] = %g %g %g' % str(velvecs))
            self.logger.debug('l [m] = %g %g %g' % str(dist_along_meter))
            self.logger.debug('nn [/cm3] = %g %g %g' % str(neutral_alongtraj))
            self.logger.debug('fp [s6/m3] = %g %g %g' % str(plasma_distfunc))
            self.logger.debug('sig [cm2] = %g %g %g' % str(crosssection))

        # Conversion to differential flux

        vel_t0 = self.observer.sensor.get_velocity_vector()  # Velocity vector in spacecraft frame.in km/s
        vel = np.sqrt((vel_t0 ** 2).sum())
        ene = f2j.ene(vel, self.enamass)

        j_ENA = f2j.f2j(f_ENA, ene, self.enamass)

        if mpl:
            rj = 71492.
            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(self.tlist, traj_coord[0, :] / rj)
            ax.plot(self.tlist, traj_coord[1, :] / rj)
            ax.plot(self.tlist, traj_coord[2, :] / rj)
            ax.set_title('Timeline of ENA trajectory (inertia)')
            if mpl_prefix != None:
                fig.savefig('%s-00.png' % mpl_prefix)

            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(traj_coord[0, :] / rj, traj_coord[1, :] / rj)
            ax.plot([0], [0], 'ro')
            ax.set_aspect('equal')
            ax.set_title('XY of ENA trajectory (inertia)')
            if mpl_prefix != None:
                fig.savefig('%s-01.png' % mpl_prefix)

            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(dist_along / rj, neutral_alongtraj, label='Nn /cm3')
            ax.plot(dist_along / rj, plasma_distfunc, label='fp s3/m6')
            ax.plot(dist_along / rj, denaflux, label='fena s3/m6 /m')
            ax.set_yscale('log')
            ax.legend(loc='best')
            ax.set_title('Fluxes')
            if mpl_prefix != None:
                fig.savefig('%s-02.png' % mpl_prefix)

        return f_ENA, j_ENA

class Visualizer:
    def __init__(self, core):
        raise NotImplementedError('')