"""Output SW2L (:mod:`fluidsim_ocean.sw2l.output`)
==================================================
.. todo::
Implement the ouput package (the most important methods)... See what is done in
:mod:`fluidsim.solvers.sw1l.output` (in the ``__init__`` file).
The methods of this class are only used in the specialized specific outputs (in
particular in print_stdout).
.. autoclass:: OutputSW2L
:members:
:private-members:
.. autosummary::
:toctree:
print_stdout
"""
import numpy as np
from fluidsim.base.output import OutputBasePseudoSpectral
from fluiddyn.util import mpi
# from .util_pythran import linear_eigenmode_from_values_1k
[docs]class OutputSW2L(OutputBasePseudoSpectral):
[docs] @staticmethod
def _complete_info_solver(info_solver):
"""Complete the ParamContainer *info_solver* with child classes to be
instantiated under *sim.output*.
This is a static method!
"""
info_solver.classes.Output._set_child("classes")
classes = info_solver.classes.Output.classes
package = "fluidsim_ocean.sw2l.output"
classes._set_child(
"PrintStdOut",
attribs={
"module_name": package + ".print_stdout",
"class_name": "PrintStdOutSW2L",
},
)
classes._set_child(
"PhysFields",
attribs={
"module_name": "fluidsim.base.output.phys_fields2d",
"class_name": "PhysFieldsBase2D",
},
)
# classes._set_child(
# "Spectra",
# attribs={
# "module_name": package + ".spectra",
# "class_name": "SpectraSW1LNormalMode",
# },
# )
# classes._set_child(
# "SpatialMeans",
# attribs={
# "module_name": package + ".spatial_means",
# "class_name": "SpatialMeansSW1L",
# },
# )
[docs] @staticmethod
def _complete_params_with_default(params, info_solver):
"""This static method is used to complete the *params* container.
"""
OutputBasePseudoSpectral._complete_params_with_default(
params, info_solver
)
# params.output.phys_fields.field_to_plot = "rot0"
params.output.phys_fields.field_to_plot = "ux1"
[docs] def compute_potential_enstrophy(self):
"""Compute total enstrophy."""
result = 0.0
for ilayer in range(self.sim.state.nb_layers):
pv = self.sim.state.get_var(f"pv{ilayer}")
hh = self.sim.state.get_var(f"h{ilayer}")
rho = self.sim.params.densities[ilayer]
result += self.sim.oper.mean_global(rho * pv ** 2 * hh)
return result
[docs] def compute_energy(self):
"""Compute total energy"""
return self.compute_energyK() + self.compute_energyP()
[docs] def compute_energyK(self):
"""Compute kinetic energy"""
result = 0.0
for ilayer in range(self.sim.state.nb_layers):
ux = self.sim.state.get_var(f"ux{ilayer}")
uy = self.sim.state.get_var(f"uy{ilayer}")
hh = self.sim.state.get_var(f"h{ilayer}")
rho = self.sim.params.densities[ilayer]
result += self.sim.oper.mean_global(
0.5 * rho * (ux ** 2 + uy ** 2) * hh
)
return result
[docs] def compute_energyP(self):
"""Compute potential energy"""
result = 0.0
for ilayer in range(self.sim.state.nb_layers):
hh = self.sim.state.get_var(f"h{ilayer}")
zz = self.sim.state.get_var(f"z{ilayer+1}")
rho = self.sim.params.densities[ilayer]
result += self.sim.oper.mean_global(
0.5 * rho * self.sim.params.g * (2.0 * zz + hh) * hh
)
return result
[docs] def compute_energyA(self):
"""Compute potential energy"""
# maybe test if reference state has been updated
result = 0.0
for ilayer in range(self.sim.state.nb_layers):
eta_up = self.sim.state.get_var(f"eta{ilayer}")
eta_down = self.sim.state.get_var(f"eta{ilayer+1}")
rho = self.sim.params.densities[ilayer]
result += self.sim.oper.mean_global(
0.5 * rho * self.sim.params.g * (eta_up ** 2 - eta_down ** 2)
)
return result
[docs] def compute_energyPref(self):
"""Compute reference potential energy"""
result = 0.0
for ilayer in range(self.sim.state.nb_layers - 1, -1, -1):
hh = self.sim.state.get_var(f"h{ilayer}")
hh_mean = self.sim.oper.mean_global(hh)
if ilayer == self.sim.state.nb_layers - 1:
zz_up = self.sim.state.get_var(f"z{ilayer}")
zz_up_mean = self.sim.oper.mean_global(zz_up)
zz_down = self.sim.state.get_var(f"z{ilayer+1}") # topo
else:
zz_down += 0.0 * zz_down + zz_up_mean
zz_up_mean += hh_mean
hh = zz_up_mean - zz_down
rho = self.sim.params.densities[ilayer]
result += self.sim.oper.mean_global(
0.5 * rho * self.sim.params.g * (2.0 * zz_down + hh) * hh
)
return result