# Source code for qgs.inner_products.base

"""
Inner products module (base class)
==================================

Abstract base classes of the structure containing the inner products :math:(\\cdot, \\, \\cdot)  between the truncated set of basis functions :math:\phi_i for the ocean and
land fields, and :math:F_i for the atmosphere fields (see :ref:files/model/oro_model:Projecting the equations on a set of basis functions).

Description of the classes
--------------------------

The three classes computing and holding the inner products of the basis functions are:

* :class:AtmosphericInnerProducts
* :class:OceanicInnerProducts
* :class:GroundInnerProducts

Warnings
--------

These are abstract base class_, they must be subclassed and the functions to compute the inner products must be defined!

.. _abstract base class: https://docs.python.org/3/glossary.html#term-abstract-base-class

"""

from abc import ABC, abstractmethod
import pickle

[docs]class AtmosphericInnerProducts(ABC):
"""Base class which contains all the atmospheric inner products coefficients needed for the tendencies
tensor :class:~.tensors.qgtensor.QgsTensor computation.
"""

def __init__(self):
self._a = None
self._u = None
self._c = None
self._b = None
self._g = None
self._d = None
self._s = None
self._z = None
self._v = None
self.stored = False

# !-----------------------------------------------------!
# ! Inner products in the equations for the atmosphere  !
# !-----------------------------------------------------!
@property
@abstractmethod
def natm(self):
"""Number of atmospheric modes."""
pass

[docs]    @abstractmethod
def a(self, i, j):
"""Function to compute the matrix of the eigenvalues of the Laplacian (atmospheric): :math:a_{i, j} = (F_i, {\\nabla}^2 F_j)."""
pass

[docs]    @abstractmethod
def u(self, i, j):
"""Function to compute the matrix of inner product: :math:u_{i, j} = (F_i, F_j)."""
pass

[docs]    @abstractmethod
def b(self, i, j, k):
"""Function to compute the tensors holding the Jacobian inner products: :math:b_{i, j, k} = (F_i, J(F_j, \\nabla^2 F_k))."""
pass

[docs]    @abstractmethod
def c(self, i, j):
"""Function to compute the matrix of beta terms for the atmosphere: :math:c_{i,j} = (F_i, \\partial_x F_j)."""
pass

[docs]    @abstractmethod
def g(self, i, j, k):
"""Function to compute tensors holding the Jacobian inner products: :math:g_{i,j,k} = (F_i, J(F_j, F_k))."""
pass

[docs]    @abstractmethod
def s(self, i, j):
"""Function to compute the forcing (thermal) of the ocean on the atmosphere: :math:s_{i,j} = (F_i, \\phi_j)."""
pass

[docs]    @abstractmethod
def d(self, i, j):
"""Function to compute the forcing of the ocean on the atmosphere: :math:d_{i,j} = (F_i, \\nabla^2 \\phi_j)."""
pass

[docs]    @abstractmethod
def z(self, i, j, k, l, m):
"""Function to compute the :math:T^4 temperature forcing for the radiation lost by atmosphere to space & ground/ocean: :math:z_{i,j,k,l,m} = (F_i, F_j F_k F_l F_m)."""
pass

[docs]    @abstractmethod
def v(self, i, j, k, l, m):
"""Function to compute the :math:T^4 temperature forcing of the ocean on the atmosphere: :math:v_{i,j,k,l,m} = (F_i, \\phi_j \\phi_k \\phi_l \\phi_m)."""
pass

[docs]    def save_to_file(self, filename, **kwargs):
"""Function to save the inner object to a file with the :mod:pickle module.

Parameters
----------
filename: str
The file name where to save the inner product object.
kwargs: dict
Keyword arguments to pass to the :mod:pickle module method.
"""
f = open(filename, 'wb')
pickle.dump(self.__dict__, f, **kwargs)
f.close()

"""Function to load previously saved inner product object with the method :meth:save_to_file.

Parameters
----------
filename: str
The file name where the inner product object was saved.
kwargs: dict
Keyword arguments to pass to the :mod:pickle module method.
"""
f = open(filename, 'rb')
f.close()

self.__dict__.clear()
self.__dict__.update(tmp_dict)

[docs]class OceanicInnerProducts(ABC):
"""Base class which contains all the oceanic inner products coefficients needed for the tendencies
tensor :class:~.tensors.qgtensor.QgsTensor computation.
"""

def __init__(self):
self._M = None
self._U = None
self._N = None
self._O = None
self._C = None
self._K = None
self._W = None
self._V = None
self._Z = None

self.stored = False

# !-----------------------------------------------------!
# ! Inner products in the equations for the ocean       !
# !-----------------------------------------------------!

@property
@abstractmethod
def noc(self):
"""Number of oceanic modes."""
pass

[docs]    @abstractmethod
def M(self, i, j):
"""Function to compute the forcing of the ocean fields on the ocean: :math:M_{i,j} = (\\phi_i, \\nabla^2 \\phi_j)."""
pass

[docs]    @abstractmethod
def U(self, i, j):
"""Function to compute the inner products: :math:U_{i,j} = (\\phi_i, \\phi_j)."""
pass

[docs]    @abstractmethod
def N(self, i, j):
"""Function computing the beta term for the ocean: :math:N_{i,j} = (\\phi_i, \\partial_x \\phi_j)."""
pass

[docs]    @abstractmethod
def O(self, i, j, k):
"""Function to compute the temperature advection term (passive scalar): :math:O_{i,j,k} = (\\phi_i, J(\\phi_j, \\phi_k))"""
pass

[docs]    @abstractmethod
def C(self, i, j, k):
"""Function to compute the tensors holding the Jacobian inner products: :math:C_{i,j,k} = (\\phi_i, J(\\phi_j,\\nabla^2 \\phi_k))."""
pass

[docs]    @abstractmethod
def K(self, i, j):
"""Function to compute the forcing of the ocean by the atmosphere: :math:K_{i,j} = (\\phi_i, \\nabla^2 F_j)."""
pass

[docs]    @abstractmethod
def W(self, i, j):
"""Function to compute the short-wave radiative forcing of the ocean: :math:W_{i,j} = (\\phi_i, F_j)."""
pass

[docs]    @abstractmethod
def Z(self, i, j, k, l, m):
"""Function to compute the :math:T^4 temperature forcing from the atmosphere to the ocean: :math:Z_{i,j,k,l,m} = (\\phi_i, F_j, F_k, F_l, F_m)."""
pass

[docs]    @abstractmethod
def V(self, i, j, k, l, m):
"""Function to compute the :math:T^4 temperature forcing from the ocean to the atmosphere: :math:V_{i,j,k,l,m} = (\\phi_i, \\phi_j, \\phi_k, \\phi_l, \\phi_m)."""
pass

[docs]    def save_to_file(self, filename, **kwargs):
"""Function to save the inner product object to a file with the :mod:pickle module.

Parameters
----------
filename: str
The file name where to save the inner product object.
kwargs: dict
Keyword arguments to pass to the :mod:pickle module method.
"""
f = open(filename, 'wb')
pickle.dump(self.__dict__, f, **kwargs)
f.close()

"""Function to load previously saved inner product object with the method :meth:save_to_file.

Parameters
----------
filename: str
The file name where the inner product object was saved.
kwargs: dict
Keyword arguments to pass to the :mod:pickle module method.
"""
f = open(filename, 'rb')
f.close()

self.__dict__.clear()
self.__dict__.update(tmp_dict)

[docs]class GroundInnerProducts(ABC):
"""Base class which contains all the ground inner products coefficients needed for the tendencies
tensor :class:~.tensors.qgtensor.QgsTensor computation.
"""

def __init__(self):
self._M = None
self._U = None
self._N = None
self._O = None
self._C = None
self._K = None
self._W = None
self._Z = None
self._V = None

self.stored = False

# !-----------------------------------------------------!
# ! Inner products in the equations for the ocean       !
# !-----------------------------------------------------!

@property
@abstractmethod
def ngr(self):
"""Number of ground modes."""
pass

[docs]    @abstractmethod
def K(self, i, j):
"""Function to compute the forcing of the ocean by the atmosphere: :math:K_{i,j} = (\\phi_i, \\nabla^2 F_j)."""
pass

[docs]    @abstractmethod
def M(self, i, j):
"""Function to compute the forcing of the ocean fields on the ocean: :math:M_{i,j} = (\\phi_i, \\nabla^2 \\phi_j)."""
pass

[docs]    @abstractmethod
def U(self, i, j):
"""Function to compute the inner products: :math:U_{i,j} = (\\phi_i, \\phi_j)."""
pass

[docs]    @abstractmethod
def N(self, i, j):
"""Function computing the beta term for the ocean: :math:N_{i,j} = (\\phi_i, \\partial_x \\phi_j)."""
pass

[docs]    @abstractmethod
def O(self, i, j, k):
"""Function to compute the temperature advection term (passive scalar): :math:O_{i,j,k} = (\\phi_i, J(\\phi_j, \\phi_k))"""
pass

[docs]    @abstractmethod
def C(self, i, j, k):
"""Function to compute the tensors holding the Jacobian inner products: :math:C_{i,j,k} = (\\phi_i, J(\\phi_j,\\nabla^2 \\phi_k))."""
pass

[docs]    @abstractmethod
def W(self, i, j):
"""Function to compute the short-wave radiative forcing of the ocean: :math:W_{i,j} = (\\phi_i, F_j)."""
pass

@abstractmethod
def V(self, i, j, k, l, m):
pass

@abstractmethod
def Z(self, i, j, k, l, m):
pass

[docs]    def save_to_file(self, filename, **kwargs):
"""Function to save the inner object to a file with the :mod:pickle module.

Parameters
----------
filename: str
The file name where to save the inner product object.
kwargs: dict
Keyword arguments to pass to the :mod:pickle module method.
"""
f = open(filename, 'wb')
pickle.dump(self.__dict__, f, **kwargs)
f.close()

"""Function to load previously saved inner product object with the method :meth:save_to_file.

Parameters
----------
filename: str
The file name where the inner product object was saved.
kwargs: dict
Keyword arguments to pass to the :mod:pickle module method.
"""
f = open(filename, 'rb')