#-*- coding: utf-8 -*-
import os
import re
import copy
import matplotlib.pyplot as plt
import numpy as np
from .log import MagicSetup
import glob
from .libmagic import fast_read, scanDir
[docs]class MagicTs(MagicSetup):
"""
This python class is used to read and plot the different time series
written by the code:
* Kinetic energy: :ref:`e_kin.TAG <secEkinFile>`
* Magnetic energy of the outer core: :ref:`e_mag_oc.TAG <secEmagocFile>`
* Magnetic energy of the inner core: :ref:`e_mag_ic.TAG <secEmagicFile>`
* Dipole information: :ref:`dipole.TAG <secDipoleFile>`
* Rotation: :ref:`rot.TAG <secRotFile>`
* Diagnostic parameters: :ref:`par.TAG <secParFile>`
* Geostrophy: :ref:`geos.TAG <secGeosFile>`
* Taylorization measures: :ref:`Tay.TAG <secTayFile>`
* Heat transfer: :ref:`heat.TAG <secHeatFile>`
* Helicity: :ref:`helicity.TAG <secHelicityFile>`
* Velocity square: :ref:`u_square.TAG <secu_squareFile>`
* Angular momentum: :ref:`AM.TAG <secAMFile>`
* Power budget: :ref:`power.TAG <secpowerFile>`
* Earth-likeness of the CMB field: :ref:`earth_like.TAG <secEarthLikeFile>`
* Parallel and perpendicular decomposition: :ref:`perpPar.TAG <secperpParFile>`
* Phase field: :ref:`phase.TAG <secphaseFile>`
* Hemisphericity: :ref:`hemi.TAG <secHemiFile>`
* RMS force balance: :ref:`dtVrms.TAG <secdtVrmsFile>`
* RMS induction terms: :ref:`dtBrms.TAG <secdtBrmsFile>`
* Time-evolution of m-spectra: :ref:`am_[kin|mag]_[pol|tor].TAG <secTimeSpectraFiles>`
Here are a couple of examples of how to use this function.
>>> # plot the most recent e_kin.TAG file found in the directoy
>>> MagicTs(field='e_kin')
>>>
>>> # stack **all** the power.TAG file found in the directory
>>> ts = MagicTs(field='power', all=True)
>>> print(ts.time, ts.buoPower) # print time and buoyancy power
>>>
>>> # If you only want to read the file ``heat.N0m2z``
>>> ts = MagicTs(field='heat', tag='N0m2z', iplot=False)
"""
[docs] def __init__(self, datadir='.', field='e_kin', iplot=True, all=False, tag=None):
"""
:param datadir: working directory
:type datadir: str
:param field: the file you want to plot
:type field: str
:param iplot: when set to True, display the plots (default True)
:type iplot: bool
:param all: when set to True, the complete time series is reconstructed by
stacking all the corresponding files from the working directory
(default False)
:type all: bool
:param tag: read the time series that exactly corresponds to the specified tag
:type tag: str
"""
self.field = field
pattern = os.path.join(datadir, 'log.*')
logFiles = scanDir(pattern)
if self.field in ('am_mag_pol','am_mag_tor','am_kin_pol','am_kin_tor'):
binary = True
else:
binary = False
if tag is not None:
pattern = os.path.join(datadir, '{}.{}'.format(self.field, tag))
files = scanDir(pattern)
# Either the log.tag directly exists and the setup is easy to obtain
if os.path.exists(os.path.join(datadir, 'log.{}'.format(tag))):
MagicSetup.__init__(self, datadir=datadir, quiet=True,
nml='log.{}'.format(tag))
# Or the tag is a bit more complicated and we need to find
# the corresponding log file
else:
st = os.path.join(datadir, r'{}\.(.*)'.format(self.field))
mask = re.compile(st)
if mask.match(files[-1]):
ending = mask.search(files[-1]).groups(0)[0]
pattern = os.path.join(datadir, 'log.{}'.format(ending))
if logFiles.__contains__(pattern):
MagicSetup.__init__(self, datadir=datadir, quiet=True,
nml='log.{}'.format(ending))
# Concatenate the files that correspond to the tag
for k, file in enumerate(files):
filename = file
data = fast_read(filename, binary=binary)
if k == 0:
tslut = TsLookUpTable(data, self.field)
else:
tslut += TsLookUpTable(data, self.field)
# If no tag is specified, the most recent is plotted
elif not all:
if len(logFiles) != 0:
MagicSetup.__init__(self, quiet=True, nml=logFiles[-1])
name = '{}.{}'.format(self.field, self.tag)
filename = os.path.join(datadir, name)
data = fast_read(filename, binary=binary)
else:
mot = '{}.*'.format(self.field)
dat = [(os.stat(i).st_mtime, i) for i in glob.glob(mot)]
dat.sort()
filename = dat[-1][1]
data = fast_read(filename, binary=binary)
tslut = TsLookUpTable(data, self.field)
# If no tag is specified but all=True, all the directory is plotted
else:
if len(logFiles) != 0:
MagicSetup.__init__(self, quiet=True, nml=logFiles[-1])
pattern = os.path.join(datadir, '{}.*'.format(self.field))
files = scanDir(pattern)
for k, file in enumerate(files):
filename = file
data = fast_read(filename, binary=binary)
if len(data) > 0: # File is not empty
if k == 0:
tslut = TsLookUpTable(data, self.field)
else:
tslut += TsLookUpTable(data, self.field)
try:
# Copy look-up table arguments into MagicTs object
for attr in tslut.__dict__:
setattr(self, attr, tslut.__dict__[attr])
if iplot:
self.plot()
except NameError: # In case tslut in not Defined
print('No file correponding to field "{}" has been found'.format(self.field))
[docs] def plot(self):
"""
Plotting subroutines. Only called if 'iplot=True'
"""
if self.field == 'e_kin':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.ekin_pol, ls='-', c='C0', label='ekin pol')
ax.plot(self.time, self.ekin_tor, ls='-', c='C1', label='ekin tor')
ax.plot(self.time, self.ekin_pol_axi, ls='--', c='C0',
label='ekin pol axi')
ax.plot(self.time, self.ekin_tor_axi, ls='--', c='C1',
label='ekin tor axi')
ax.plot(self.time, self.ekin_tot, ls='-', c='0.25', label='ekin tot')
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Ekin')
ax.set_yscale('log')
ax.set_xlim(self.time.min(), self.time.max())
fig.tight_layout()
elif self.field == 'e_mag_oc':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.emagoc_pol, ls='-', c='C0', label='emag pol')
ax.plot(self.time, self.emagoc_tor, ls='-', c='C1', label='emag tor')
ax.plot(self.time, self.emagoc_pol_axi, ls='--', c='C0',
label='emag pol axi')
ax.plot(self.time, self.emagoc_tor_axi, ls='--', c='C1',
label='emag tor axi')
ax.plot(self.time, self.emag_tot, ls='-', c='0.25', label='emag tot')
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Emag')
ax.set_yscale('log')
ax.set_xlim(self.time[0], self.time[-1])
fig.tight_layout()
# fig,ax = plt.subplots(1)
# ax.plot(self.time, self.emag_es, ls='-',
# label=r'${E_B}^S$')
# ax.plot(self.time, self.emag_eas, ls='-',
# label=r'${E_B}^A$')
# ax.legend(loc='best', frameon=False)
# ax.set_xlabel('Time')
# ax.set_ylabel('Emag')
elif self.field == 'e_mag_ic':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.emagic_pol, ls='-', c='C0', label='emagic pol')
ax.plot(self.time, self.emagic_tor, ls='-', c='C1', label='emagic tor')
ax.plot(self.time, self.emagic_pol_axi, ls='--', c='C0',
label='emagic pol axi')
ax.plot(self.time, self.emagic_tor_axi, ls='--', c='C1',
label='emagic tor axi')
ax.plot(self.time, self.emagic_pol+self.emagic_tor, ls='-', c='0.25',
label='emagic tot')
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Emag inner core')
ax.set_yscale('log')
ax.set_xlim(self.time[0], self.time[-1])
fig.tight_layout()
elif self.field == 'rot':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.omega_ic, ls='-', label='Omega IC')
if abs(self.omega_ma).max() > 0.:
ax.plot(self.time, self.omega_ma, ls='-', label='Omega MA')
ax.set_xlabel('Time')
ax.set_ylabel('Rotation')
ax.legend(loc='best', frameon=False)
ax.set_xlim(self.time[0], self.time[-1])
fig.tight_layout()
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
if abs(self.lorentz_torque_ic).max() > 0.:
ax1.plot(self.time, self.lorentz_torque_ic, ls='-',
label='Lorentz torque on IC')
if abs(self.viscous_torque_ic).max() > 0.:
ax1.plot(self.time, self.viscous_torque_ic, ls='-',
label='Viscous torque on IC')
if abs(self.gravi_torque_ic).max() > 0.:
ax1.plot(self.time, self.gravi_torque_ic, ls='-',
label='Gravitationnal torque on IC')
ax1.legend(loc='best', frameon=False)
ax1.set_xlabel('Time')
ax1.set_ylabel('Torques on IC')
ax1.set_xlim(self.time[0], self.time[-1])
ax1.ticklabel_format(axis='y', style='sci', scilimits=(0,0))
ax1.axhline(0., color='0.5', ls='--', lw=1)
fig1.tight_layout()
if abs(self.omega_ma).max() > 0.:
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
if abs(self.lorentz_torque_ma).max() > 0.:
ax2.plot(self.time, self.lorentz_torque_ma, ls='-',
label='Lorentz torque on mantle')
if abs(self.viscous_torque_ma).max() > 0.:
ax2.plot(self.time, self.viscous_torque_ma, ls='-',
label='Viscous torque on mantle')
if abs(self.gravi_torque_ma).max() > 0.:
ax2.plot(self.time, self.gravi_torque_ma, ls='-',
label='Gravitationnal torque on mantle')
ax2.legend(loc='best', frameon=False)
ax2.set_xlabel('Time')
ax2.set_ylabel('Torques on mantle')
ax2.set_xlim(self.time[0], self.time[-1])
ax2.ticklabel_format(axis='y', style='sci', scilimits=(0,0))
ax2.axhline(0., color='0.5', ls='--', lw=1)
fig2.tight_layout()
elif self.field == 'timestep':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.step(self.time, self.dt)
ax.set_yscale('log')
ax.set_xlabel('Time')
ax.set_ylabel('Time step size')
fig.tight_layout()
elif self.field == 'dipole':
if self.ktopb != 2:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.theta_dip, label='theta_dip')
#ax.plot(self.time, self.phi_dip, 'r-', label='phi_dip')
ax.set_ylabel('Dipole angle')
ax.set_xlabel('Time')
ax.set_ylim(-1., 181)
ax.set_xlim(self.time[0], self.time[-1])
fig.tight_layout()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.dipTot, label='Total dipolarity')
ax.plot(self.time, self.dipolarity, ls='--', label='Axisym dipolarity')
ax.plot(self.time, self.dipTot_cmb, ls='-', c='C2',
label='Total dipolarity CMB')
ax.plot(self.time, self.dip_cmb, ls='--', c='C2',
label='Axisym dipolarity')
if hasattr(self, 'l_geo'):
lcut = self.l_geo
else:
lcut = 11
ax.plot(self.time, self.dip_l11, ls='-', c='C3',
label='Axisym dip l={:d}'.format(lcut))
ax.plot(self.time, self.dipTot_l11, ls='--', c='C3',
label='Total dip l={:d}'.format(lcut))
# ax.plot(self.time, self.dip3, ls='-', c='#e5ae38',
# label='Epol axi/Ecmb')
ax.legend(loc='best', frameon=False)
ax.set_ylabel('Dipolarity')
ax.set_xlabel('Time')
ax.set_ylim(0, 1)
ax.set_xlim(self.time[0], self.time[-1])
fig.tight_layout()
elif self.field == 'AM':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.am_oc_z, label='Outer core')
if abs(self.am_ic).max() > 0.:
ax.plot(self.time, self.am_ic, label='Inner core')
if abs(self.am_ma).max() > 0.:
ax.plot(self.time, self.am_ma, label='Mantle')
ax.plot(self.time, self.amz, ls='-', c='0.25', label='Total')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False)
fig.tight_layout()
elif self.field == 'par':
fig = plt.figure()
ax = fig.add_subplot(111)
if self.mode == 1 or self.prmag == 0.:
ax.semilogy(self.time, self.rm, label='Reynolds')
else:
ax.semilogy(self.time, self.rm, label='Magnetic Reynolds')
if self.elsasser.max() > 0.:
ax.semilogy(self.time, self.elsasser, label='Elsasser')
ax.semilogy(self.time, self.els_cmb, label='Elsasser CMB')
ax.semilogy(self.time, self.rossby_l, label='Rossby l')
if hasattr(self, 'rolc'):
ax.semilogy(self.time, self.rolc, label='Roc l')
ax.legend(loc='lower right', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Params')
ax.set_xlim(self.time[0], self.time[-1])
fig.tight_layout()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.semilogy(self.time, self.dlV, label='Integral (ell)')
ax.semilogy(self.time, self.dlVc, label='Integral (ell c)')
ax.semilogy(self.time, self.dmV, label='Integral (m)')
ax.semilogy(self.time, self.dlPolPeak, label='Peak (pol)')
if abs(self.lbDiss).max() > 0.:
ax.semilogy(self.time, self.lbDiss, label='Magnetic dissipation')
if abs(self.lvDiss).max() > 0.:
ax.semilogy(self.time, self.lvDiss, label='Viscous dissipation')
ax.set_xlabel('Time')
ax.set_ylabel('Lengthscales')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False)
fig.tight_layout()
if self.dipolarity.max() > 0.:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.dipolarity, label='Dipolarity')
ax.plot(self.time, self.dip_cmb, label='Dipolarity CMB')
ax.legend(loc='upper right', frameon=False)
ax.set_xlim(self.time[0], self.time[-1])
ax.set_xlabel('Time')
ax.set_ylabel('Dipolarity')
ax.set_ylim(0, 1)
fig.tight_layout()
elif self.field == 'geos':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.geos, label='Total')
ax.plot(self.time, self.geosM, label='Meridional')
ax.plot(self.time, self.geosZ, label='Zonal')
ax.plot(self.time, self.geosNAP, label='Non-axi perp')
ax.set_xlabel('Time')
ax.set_ylabel('Geostrophy')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False)
fig.tight_layout()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.corr_vz_otc, label='uz')
ax.plot(self.time, self.corr_vortz_otc, label='z vorticity')
ax.plot(self.time, self.corr_hel_otc, label='Helicity')
ax.set_xlabel('Time')
ax.set_ylabel('z correlations')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False)
fig.tight_layout()
elif self.field == 'phase':
fig = plt.figure()
ax = fig.add_subplot(111)
ax1 = ax.twinx()
mask = (self.rmelt > 0)
ax.plot(self.time[mask], self.rmelt[mask], label='r melt', color='C0')
ax.plot(self.time, self.rmelt_mean, label='r melt', color='C0', ls=':')
#ax.plot(self.time, self.rmelt_min, ls='--', color='C0', alpha=0.5)
#ax.plot(self.time, self.rmelt_max, ls='--', color='C0', alpha=0.5)
ax1.plot(self.time[mask], self.trmelt[mask], label='T(r melt)', color='C1')
ax1.plot(self.time, self.trmelt_mean, label='T(r melt)', color='C1',
ls=':')
ax.set_xlim(self.time[0], self.time[-1])
ax.set_xlabel('Time')
ax.set_ylabel('r melt')
ax1.set_ylabel('T(r melt)')
fig.tight_layout()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.semilogy(self.time, self.ekinS/self.ekinL)
ax.set_xlim(self.time[0], self.time[-1])
ax.set_xlabel('Time')
ax.set_ylabel('Relative energy fraction in solidus')
fig.tight_layout()
elif self.field == 'hemi':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.hemi_emag, label='Emag')
ax.plot(self.time, self.hemi_br, label='|Br| volume')
ax.plot(self.time, self.hemi_cmb, label='|Br| CMB')
ax.set_xlabel('Time')
ax.set_ylabel('Hemisphericity')
ax.set_xlim(self.time[0], self.time[-1])
ax.set_ylim(0., 1.)
#ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False)
fig.tight_layout()
elif self.field == 'earth_like':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.axial_dipole, label='AD/NAD')
ax.plot(self.time, self.symmetry, label='O/E')
ax.plot(self.time, self.zonality, label='Z/NZ')
ax.plot(self.time, self.flux_concentration, label='FCF')
ax.set_xlim(self.time[0], self.time[-1])
ax.set_xlabel('Time')
ax.set_ylabel('Rating parameters')
ax.legend(loc='upper right', frameon=False)
fig.tight_layout()
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
ax1.plot(self.time, self.chi_square)
ax1.set_xlim(self.time[0], self.time[-1])
ax1.set_xlabel('Time')
ax1.set_ylabel('Chi square')
fig1.tight_layout()
elif self.field == 'misc':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.topnuss, label='Top Nusselt')
ax.plot(self.time, self.botnuss, label='Bottom Nusselt')
ax.legend(loc='lower right', frameon=False)
ax.set_xlim(self.time[0], self.time[-1])
ax.set_xlabel('Time')
ax.set_ylabel('Nusselt number')
fig.tight_layout()
if self.helrms.max() != 0.:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.helrms)
ax.set_xlim(self.time[0], self.time[-1])
ax.set_xlabel('Time')
ax.set_ylabel('Helicity')
fig.tight_layout()
elif self.field == 'heat':
fig = plt.figure()
ax = fig.add_subplot(111)
if self.kbots == 2 and self.ktops == 2:
ax.plot(self.time, self.deltaTnuss, label=r'$Nu_{\Delta T}$')
else:
ax.plot(self.time, self.topnuss, label='Top Nusselt')
ax.plot(self.time, self.botnuss, label='Bottom Nusselt')
ax.set_xlim(self.time.min(), self.time.max())
ax.legend(loc='lower right', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Nusselt number')
fig.tight_layout()
if self.topsherwood.max() != 1.0 or self.deltasherwood.max() != 1.0:
fig = plt.figure()
ax = fig.add_subplot(111)
if self.kbotxi == 2 and self.ktopxi == 2:
ax.plot(self.time, self.deltasherwood, label=r'$Sh_{\Delta \xi}$')
else:
ax.plot(self.time, self.topsherwood, label='Top Sherwood')
ax.plot(self.time, self.botsherwood, label='Bottom Sherwood')
ax.legend(loc='lower right', frameon=False)
ax.set_xlim(self.time.min(), self.time.max())
ax.set_xlabel('Time')
ax.set_ylabel('Sherwood number')
fig.tight_layout()
elif self.field == 'helicity':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.helRMSN, label='Northern Hemisphere')
ax.plot(self.time, self.helRMSS, label='Southern Hemisphere')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='lower right', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Helicity')
fig.tight_layout()
elif self.field == 'u_square':
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.ekin_pol, ls='-', c='C0', label='ekin pol')
ax.plot(self.time, self.ekin_tor, ls='-', c='C1', label='ekin tor')
ax.plot(self.time, self.ekin_pol_axi, ls='--', c='C0',
label='ekin pol axi')
ax.plot(self.time, self.ekin_tor_axi, ls='--', c='C1',
label='ekin tor axi')
ax.plot(self.time, self.ekin_tot, ls='-', c='0.25', label='ekin tot')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('u**2')
ax.set_yscale('log')
fig.tight_layout()
fig = plt.figure()
ax = fig.add_subplot(111)
if self.mode == 1 or self.prmag == 0.:
ax.semilogy(self.time, self.rm, label='Reynolds')
else:
ax.semilogy(self.time, self.rm, label='Magnetic Reynolds')
ax.semilogy(self.time, self.ro, label='Rossby')
ax.semilogy(self.time, self.rossby_l, label='Rossby l')
ax.semilogy(self.time, self.dl, label='l')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='lower right', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Params')
fig.tight_layout()
elif self.field in ('dtVrms'):
fig = plt.figure() # Poloidal forces
ax = fig.add_subplot(111)
ax.semilogy(self.time, self.CorRms, label='Coriolis')
ax.semilogy(self.time, self.PreRms, label='Pressure')
ax.semilogy(self.time, self.LFRms, label='Lorentz')
ax.semilogy(self.time, self.BuoRms, label='Thermal Buoyancy')
if abs(self.ChemRms).max() > 0:
ax.semilogy(self.time, self.ChemRms, label='Chemical Buoyancy')
ax.semilogy(self.time, self.InerRms, label='Inertia')
ax.semilogy(self.time, self.DifRms, label='Diffusion')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False, ncol=2)
ax.set_xlabel('Time')
ax.set_ylabel('RMS forces')
fig.tight_layout()
fig = plt.figure() # Toroidal forces
ax = fig.add_subplot(111)
ax.semilogy(self.time, self.geos, label='Geostrophic balance')
ax.semilogy(self.time, self.mageos, label='Magnetostrophic')
ax.semilogy(self.time, self.arc, label='Archimedean')
ax.semilogy(self.time, self.arcMag, label='Archimedean+Lorentz')
ax.semilogy(self.time, self.corLor, label='Coriolis/Lorentz')
ax.semilogy(self.time, self.preLor, label='Pressure/Lorentz')
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('RMS balances')
ax.set_xlim(self.time[0], self.time[-1])
fig.tight_layout()
elif self.field == 'perpPar':
fig = plt.figure()
ax= fig.add_subplot(111)
ax.plot(self.time, self.eperp, ls='-', c='C0', label='ekin perp')
ax.plot(self.time, self.epar, ls='-', c='C1', label='ekin par')
ax.plot(self.time, self.eperp_axi, ls='--', c='C0',
label='ekin perp axi')
ax.plot(self.time, self.epar_axi, ls='--', c='C1',
label='ekin par axi')
ax.plot(self.time, self.ekin_tot, ls='-', c='0.25', label='ekin tot')
ax.plot(self.time, self.ekin_tot, 'k-')
ax.set_xlim(self.time[0], self.time[-1])
ax.set_yscale('log')
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Kinetic energy')
ax.set_xlim(self.time[0], self.time[-1])
fig.tight_layout()
elif self.field in ('power'):
fig = plt.figure()
ax = fig.add_subplot(111)
if self.buoPower.max() != 0.:
ax.semilogy(self.time, self.buoPower, label='Thermal buoyancy')
if self.buoPower_chem.max() != 0.:
ax.semilogy(self.time, self.buoPower_chem,
label='Chemical buoyancy')
if self.ohmDiss.max() != 0.:
ax.semilogy(self.time, -self.ohmDiss, label='Ohmic diss.')
ax.semilogy(self.time, -self.viscDiss, label='Viscous diss.')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Power')
fig.tight_layout()
if hasattr(self,'fohm'):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(self.time, self.fohm)
ax.set_xlim(self.time[0], self.time[-1])
ax.set_ylim(0., 1.)
ax.set_xlabel('Time')
ax.set_ylabel('fohm')
fig.tight_layout()
elif self.field in ('dtBrms'):
fig = plt.figure() # Poloidal
ax = fig.add_subplot(111)
ax.semilogy(self.time, self.DynPolRms, label='Induction')
ax.semilogy(self.time, self.DifPolRms, label='Diffusion')
ax.semilogy(self.time, self.dtBpolRms, label='Time derivative')
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Poloidal field production')
fig.tight_layout()
fig = plt.figure() # Toroidal
ax = fig.add_subplot(111)
ax.semilogy(self.time, self.DynTorRms, label='Induction')
ax.semilogy(self.time, self.DifTorRms, label='Diffusion')
ax.semilogy(self.time, self.omEffect*self.DynTorRms,
label='Omega effect')
ax.semilogy(self.time, self.dtBtorRms, label='Time derivative', )
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Toroidal field production')
fig.tight_layout()
elif self.field in ('SRIC'):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.semilogy(self.time, self.viscTorq, label='Viscous')
ax.semilogy(self.time, self.LorTorq, label='Lorentz')
ax.semilogy(self.time, self.totTorq, label='Total')
ax.set_xlim(self.time[0], self.time[-1])
ax.legend(loc='best', frameon=False)
ax.set_xlabel('Time')
ax.set_ylabel('Torque')
fig.tight_layout()
elif self.field in ('am_mag_pol', 'am_mag_tor', 'am_kin_pol', 'am_kin_tor'):
fig = plt.figure()
ax = fig.add_subplot(111)
for k in range(self.coeffs.shape[1]):
ax.semilogy(self.time, self.coeffs[:, k], label='m={}'.format(k))
ax.set_xlabel('Time')
if self.coeffs.shape[1] < 20:
ax.legend(loc='best', frameon=False)
if self.field == 'am_mag_pol':
ax.set_ylabel('Emag poloidal')
elif self.field == 'am_mag_tor':
ax.set_ylabel('Emag toroidal')
elif self.field == 'am_kin_pol':
ax.set_ylabel('Ekin poloidal')
elif self.field == 'am_kin_tor':
ax.set_ylabel('Ekin toroidal')
ax.set_xlim(self.time[0], self.time[-1])
fig.tight_layout()
class TsLookUpTable:
"""
The purpose of this class is to create a lookup table between the numpy
array that comes from the reading of the time series and the corresponding
column.
"""
def __init__(self, data, field):
"""
:param data: numpy array that contains the data
:type data: numpy.ndarray
:param field: name of the field (i.e. 'eKinR', 'eMagR', 'powerR', ...)
:type field: str
"""
self.field = field
if self.field == 'e_kin':
self.time = data[:, 0]
self.ekin_pol = data[:, 1]
self.ekin_tor = data[:, 2]
self.ekin_pol_axi = data[:, 3]
self.ekin_tor_axi = data[:, 4]
self.ekin_pol_es = data[:, 5]
self.ekin_tor_es = data[:, 6]
self.ekin_pol_es_axi = data[:, 7]
self.ekin_tor_es_axi = data[:, 8]
self.ekin_tot = self.ekin_pol + self.ekin_tor
self.ekin_axi = self.ekin_pol_axi + self.ekin_tor_axi
self.ekin_es = self.ekin_pol_es + self.ekin_tor_es
self.ekin_es_axi = self.ekin_pol_es_axi + self.ekin_tor_es_axi
self.ekin_pol_naxi = self.ekin_pol-self.ekin_pol_axi
self.ekin_tor_naxi = self.ekin_tor-self.ekin_tor_axi
self.ekin_es_naxi = self.ekin_es-self.ekin_es_axi
self.ekin_naxi = self.ekin_tot-self.ekin_pol_axi-self.ekin_tor_axi
elif self.field == 'e_mag_oc':
self.time = data[:, 0]
self.emagoc_pol = data[:, 1]
self.emagoc_tor = data[:, 2]
self.emagoc_pol_axi = data[:, 3]
self.emagoc_tor_axi = data[:, 4]
self.ext_nrj_pol = data[:, 5]
self.ext_nrj_pol_axi = data[:, 6]
self.emagoc_pol_eas = data[:, 7]
self.emagoc_tor_eas = data[:, 8]
self.emagoc_pol_eas_axi = data[:, 9]
self.emagoc_tor_eas_axi = data[:, 10]
self.emag_tot = self.emagoc_pol + self.emagoc_tor
self.emag_axi = self.emagoc_pol_axi + self.emagoc_tor_axi
self.emag_eas = self.emagoc_pol_eas + self.emagoc_tor_eas
self.emag_eas_axi = self.emagoc_pol_eas_axi + self.emagoc_tor_eas_axi
elif self.field == 'e_mag_ic':
self.time = data[:, 0]
self.emagic_pol = data[:, 1]
self.emagic_tor = data[:, 2]
self.emagic_pol_axi = data[:, 3]
self.emagic_tor_axi = data[:, 4]
self.emagic_tot = self.emagic_pol + self.emagic_tor
elif self.field == 'timestep':
self.time = data[:, 0]
self.dt = data[:, 1]
elif self.field == 'dipole':
self.time = data[:, 0]
self.theta_dip = data[:, 1]
self.phi_dip = data[:, 2]
self.dipolarity = data[:, 3]
self.dip_cmb = data[:, 4]
self.dip_l11 = data[:, 5] # Cut at l=11
self.dipTot = data[:, 6] # Also non axisymmetric dipole
self.dipTot_cmb = data[:, 7] # Non-axi at the CMB
self.dipTot_l11 = data[:, 8] # Cut at l=11
self.e_dip_cmb = data[:, 9]
self.e_dip_ax_cmb = data[:, 10]
self.e_dip = data[:, 11]
self.e_dip_ax = data[:, 12]
self.ecmb = data[:, 13]
self.egeo = data[:, 14]
self.ratio_cmb_as = data[:, 16] # (e_cmb-e_es_cmb)/e_cmb
self.ratio_cmb_naxi = data[:, 17] # (e_cmb-e_axi_cmb)/e_cmb
self.ratio_l11_cmb_as = data[:, 18] # (e_geo-e_es_geo)/e_geo
self.ratio_l11_cmb_naxi = data[:, 19] # (e_geo-e_axi_geo)/e_geo
self.epol_axi_cmb = (-self.ratio_cmb_naxi*self.ecmb+self.ecmb)
self.epol_rel_cmb = self.epol_axi_cmb/self.ecmb
self.fdip = np.sqrt(self.dip_l11)
elif self.field == 'AM':
self.time = data[:, 0]
self.am_oc_x = data[:, 1]
self.am_oc_y = data[:, 2]
self.am_oc_z = data[:, 3]
self.am_ic = data[:, 4]
self.am_ma = data[:, 5]
self.amz = data[:, 6]
self.damzdt = data[:, 7]
elif self.field == 'rot':
self.time = data[:, 0]
self.omega_ic = data[:, 1]
self.lorentz_torque_ic = data[:, 2]
self.viscous_torque_ic = data[:, 3]
self.omega_ma = data[:, 4]
self.lorentz_torque_ma = data[:, 5]
self.viscous_torque_ma = data[:, 6]
if data.shape[-1] == 8:
self.gravi_torque_ic = data[:, 7]
else:
self.gravi_torque_ic = np.zeros_like(self.omega_ic)
self.gravi_torque_ma = -self.gravi_torque_ic
elif self.field == 'Tay':
self.time = data[:, 0]
self.ekin_tora_rel = data[:, 1]
self.egeos_rel = data[:, 2]
self.tay = data[:, 3]
self.tayR = data[:, 4]
self.tayV = data[:, 5]
self.ekin_cyl = data[:, 6]
elif self.field == 'par':
self.time = data[:, 0]
self.rm = data[:, 1]
self.elsasser = data[:, 2]
self.rossby_l = data[:, 3]
self.geos = data[:, 4]
self.dipolarity = data[:, 5]
self.dip_cmb = data[:, 6]
self.dlV = data[:, 7]
self.dmV = data[:, 8]
self.lvDiss = data[:, 11]
self.lbDiss = data[:, 12]
self.dlB = data[:, 13]
self.dmB = data[:, 14]
self.els_cmb = data[:, 15]
if data.shape[-1] > 16:
self.rolc = data[:, 16]
self.dlVc = data[:, 17]
self.reEquat = data[:, 18]
self.dlPolPeak = np.zeros_like(self.time)
if data.shape[-1] == 20:
self.dlPolPeak = data[:, 18]
self.reEquat = data[:, 19]
else:
self.rolc = np.zeros_like(self.time)
self.dlVc = np.zeros_like(self.time)
self.reEquat = np.zeros_like(self.time)
self.dlPolPeak = np.zeros_like(self.time)
elif self.field == 'misc':
self.time = data[:, 0]
self.botnuss = data[:, 1]
self.topnuss = data[:, 2]
self.bottemp = data[:, 3] / np.sqrt(4.*np.pi)
self.toptemp = data[:, 4] / np.sqrt(4.*np.pi)
self.helrms = data[:, 8]
self.helN = data[:, 5]*self.helrms
self.helS = data[:, 6]*self.helrms
try:
self.botflux = data[:, 16]
self.topflux = data[:, 17]
except IndexError:
self.botflux = np.zeros_like(self.time)
self.topflux = np.zeros_like(self.time)
pass
elif self.field == 'geos':
self.time = data[:, 0]
self.geos = data[:, 1]
self.ekin_ntc_rel = data[:, 2]
self.ekin_stc_rel = data[:, 3]
self.ekin = data[:, 4]
self.corr_vz_otc = data[:, 5]
self.corr_vortz_otc = data[:, 6]
self.corr_hel_otc = data[:, 7]
if data.shape[-1] == 8:
self.geosA= np.zeros_like(self.time)
self.geosZ= np.zeros_like(self.time)
self.geosM= np.zeros_like(self.time)
self.geosNAP = np.zeros_like(self.time)
elif data.shape[-1] == 12:
self.geosA = data[:, 8]
self.geosZ = data[:, 9]
self.geosM = data[:, 10]
self.geosNAP = data[:, 11]
elif self.field == 'heat':
self.time = data[:, 0]
self.botnuss = data[:, 1]
self.topnuss = data[:, 2]
self.deltaTnuss = data[:, 3]
self.bottemp = data[:, 4]
self.toptemp = data[:, 5]
self.bots = data[:, 6]
self.tops = data[:, 7]
self.topflux = data[:, 8]
self.botflux = data[:, 9]
self.toppress = data[:, 10]
self.mass = data[:, 11]
try:
self.botsherwood = data[:, 12]
self.topsherwood = data[:, 13]
self.deltasherwood = data[:, 14]
self.botxi = data[:, 15]
self.topxi = data[:, 16]
except IndexError:
self.topsherwood = np.ones_like(self.time)
self.botsherwood = np.ones_like(self.time)
self.deltasherwood = np.ones_like(self.time)
self.botxi = np.zeros_like(self.time)
self.topxi = np.zeros_like(self.time)
pass
elif self.field == 'helicity':
self.time = data[:, 0]
self.helN = data[:, 1]
self.helS = data[:, 2]
self.helRMSN = data[:, 3]
self.helRMSS = data[:, 4]
self.helnaN = data[:, 5]
self.helnaS = data[:, 6]
self.helnaRMSN = data[:, 7]
self.helnaRMSS = data[:, 8]
elif self.field == 'earth_like':
self.time = data[:, 0]
self.axial_dipole = data[:, 1]
self.symmetry = data[:, 2]
self.zonality = data[:, 3]
self.flux_concentration = data[:, 4]
self.chi_square = ((np.log(self.axial_dipole)-np.log(1.4))/np.log(2.))**2+\
((np.log(self.symmetry)-np.log(1.))/np.log(2.))**2+\
((np.log(self.zonality)-np.log(0.15))/np.log(2.5))**2+\
((np.log(self.flux_concentration)-np.log(1.5))/np.log(1.75))**2
elif self.field == 'u_square':
self.time = data[:, 0]
self.ekin_pol = data[:, 1]
self.ekin_tor = data[:, 2]
self.ekin_pol_axi = data[:, 3]
self.ekin_tor_axi = data[:, 4]
self.ekin_tot = self.ekin_pol + self.ekin_tor
self.ro = data[:, 5]
self.rm = data[:, 6]
self.rossby_l = data[:, 7]
self.dl = data[:, 8]
elif self.field == 'perpPar':
self.time = data[:, 0]
self.eperp = data[:, 1]
self.epar = data[:, 2]
self.eperp_axi = data[:, 3]
self.epar_axi = data[:, 4]
self.ekin_tot = self.eperp+self.epar
elif self.field == 'phase':
self.time = data[:, 0]
self.rmelt_mean = data[:, 1]
self.trmelt_mean = data[:, 2]
if data.shape[1] == 9:
self.trmelt = np.zeros_like(self.trmelt_mean)
self.rmelt = np.zeros_like(self.rmelt_mean)
self.rmelt_min = np.zeros_like(self.rmelt)
self.rmelt_max = np.zeros_like(self.rmelt)
self.volS = data[:, 3]
self.ekinS = data[:, 4]
self.ekinL = data[:, 5]
self.flux_cmb = data[:, 6]
self.flux_icb = data[:, 7]
self.dEnthdt = data[:, 8]
self.phase_min = np.zeros_like(self.rmelt)
self.phase_max = np.zeros_like(self.rmelt)
else:
self.rmelt = data[:, 3]
self.trmelt = data[:, 4]
self.rmelt_min = data[:, 5]
self.rmelt_max = data[:, 6]
self.volS = data[:, 7]
self.ekinS = data[:, 8]
self.ekinL = data[:, 9]
self.flux_cmb = data[:, 10]
self.flux_icb = data[:, 11]
self.dEnthdt = data[:, 12]
if data.shape[1] == 15:
self.phase_min = data[:, 13]
self.phase_max = data[:, 14]
else:
self.phase_min = np.zeros_like(self.rmelt)
self.phase_max = np.zeros_like(self.rmelt)
elif self.field == 'hemi':
self.time = data[:, 0]
self.hemi_vr = data[:, 1]
self.hemi_ekin = data[:, 2]
self.hemi_br = data[:, 3]
self.hemi_emag = data[:, 4]
self.hemi_cmb = data[:, 5]
self.ekin = data[:, 6]
self.emag = data[:, 7]
elif self.field == 'dtVrms':
self.time = data[:, 0]
self.InerRms = data[:, 1]
self.CorRms = data[:, 2]
self.LFRms = data[:, 3]
self.AdvRms = data[:, 4]
self.DifRms = data[:, 5]
self.BuoRms = data[:, 6]
if data.shape[1] == 14:
self.PreRms = data[:, 7]
self.geos = data[:, 8] # geostrophic balance
self.mageos = data[:, 9] # magnetostrophic balance
self.arcMag = data[:, 10] # Coriolis/Pressure/Buoyancy/Lorentz
self.corLor = data[:, 11] # Coriolis/Lorentz
self.preLor = data[:, 12] # Pressure/Lorentz
self.cia = data[:, 13] # Coriolis/Inertia/Archmedean
self.arc = np.zeros_like(self.geos)
self.ChemRms = np.zeros_like(self.geos)
elif data.shape[1] == 15:
self.PreRms = data[:, 7]
self.geos = data[:, 8] # geostrophic balance
self.mageos = data[:, 9] # magnetostrophic balance
self.arc = data[:, 10] # Coriolis/Pressure/Buoyancy
self.arcMag = data[:, 11] # Coriolis/Pressure/Buoyancy/Lorentz
self.corLor = data[:, 12] # Coriolis/Lorentz
self.preLor = data[:, 13] # Pressure/Lorentz
self.cia = data[:, 14] # Coriolis/Inertia/Archmedean
self.ChemRms = np.zeros_like(self.geos)
elif data.shape[1] == 16:
self.ChemRms = data[:, 7]
self.PreRms = data[:, 8]
self.geos = data[:, 9] # geostrophic balance
self.mageos = data[:, 10] # magnetostrophic balance
self.arc = data[:, 11] # Coriolis/Pressure/Buoyancy
self.arcMag = data[:, 12] # Coriolis/Pressure/Buoyancy/Lorentz
self.corLor = data[:, 13] # Coriolis/Lorentz
self.preLor = data[:, 14] # Pressure/Lorentz
self.cia = data[:, 15] # Coriolis/Inertia/Archmedean
elif data.shape[1] == 18:
self.ChemRms = data[:, 7]
self.PreRms = data[:, 8]
self.MagTensRms = data[:, 9] # Magnetic tension
self.MagPreRms = data[:, 10] # Magnetic pressure
self.geos = data[:, 11] # geostrophic balance
self.mageos = data[:, 12] # magnetostrophic balance
self.arc = data[:, 13] # Coriolis/Pressure/Buoyancy
self.arcMag = data[:, 14] # Coriolis/Pressure/Buoyancy/Lorentz
self.corLor = data[:, 15] # Coriolis/Lorentz
self.preLor = data[:, 16] # Pressure/Lorentz
self.cia = data[:, 17] # Coriolis/Inertia/Archmedean
elif self.field == 'dtBrms':
self.time = data[:, 0]
self.dtBpolRms = data[:, 1]
self.dtBtorRms = data[:, 2]
self.DynPolRms = data[:, 3]
self.DynTorRms = data[:, 4]
self.DifPolRms = data[:, 5]
self.DifTorRms = data[:, 6]
self.omEffect = data[:, 7]
self.omega = data[:, 8]
self.DynDipRms = data[:, 9]
self.DynDipAxRms = data[:, 10]
elif self.field == 'dtE':
self.time = data[:, 0]
self.dEdt = data[:, 1]
self.intdEdt = data[:, 2]
self.reldEdt = data[:, 3]
elif self.field == 'power':
self.time = data[:, 0]
self.buoPower = data[:, 1]
if data.shape[1] == 11:
self.buoPower_chem = data[:, 2]
self.icrotPower = data[:, 3]
self.mantlerotPower = data[:, 4]
self.viscDiss = data[:, 5]
self.ohmDiss = data[:, 6]
self.icPower = data[:, 7]
self.mantlePower = data[:, 8]
elif data.shape[1] == 10:
self.buoPower_chem = np.zeros_like(self.time)
self.icrotPower = data[:, 2]
self.mantlerotPower = data[:, 3]
self.viscDiss = data[:, 4]
self.ohmDiss = data[:, 5]
self.icPower = data[:, 6]
self.mantlePower = data[:, 7]
if abs(self.ohmDiss).max() != 0:
self.fohm = -self.ohmDiss/(self.buoPower+self.buoPower_chem)
self.fvis = -self.viscDiss/(self.buoPower+self.buoPower_chem)
elif self.field == 'SRIC':
self.time = data[:,0]
self.omega_ic = data[:,1]
self.viscPower = data[:,2]
self.totPower = data[:,3]
self.LorPower = data[:,4]
self.viscTorq = abs(self.viscPower/self.omega_ic)
self.totTorq = abs(self.totPower/self.omega_ic)
self.LorTorq = abs(self.LorPower/self.omega_ic)
elif self.field in ('am_mag_pol', 'am_mag_tor', # Tayler instability
'am_kin_pol', 'am_kin_tor'):
self.time = data[:, 0]
self.coeffs = data[:, 1:]
else:
print('The field "{}" is not know'.format(self.field))
def __add__(self, new):
"""
This method allows to sum two look up tables together. This is python
built-in method.
"""
out = copy.deepcopy(new)
timeOld = self.time[-1]
timeNew = new.time[0]
for attr in new.__dict__.keys():
if attr == 'coeffs':
out.__dict__[attr] = np.vstack((self.__dict__[attr],
out.__dict__[attr][1:, :]))
elif attr != 'field':
if attr in self.__dict__.keys(): # If the argument already existed
if timeOld != timeNew:
out.__dict__[attr] = np.hstack((self.__dict__[attr],
out.__dict__[attr]))
else: # Same time
out.__dict__[attr] = np.hstack((self.__dict__[attr],
out.__dict__[attr][1:]))
return out