Source code for hydrac.model.scattering.emp

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Empirically based model (:mod:`hydrac.model.scattering.emp`)
============================================================

.. autoclass:: Emp
   :members:
   :private-members:

"""

import numpy as np
from hydrac.util.parameters import Parameters


[docs]class Emp(object): """Empirical models class. This class deals with empirically defined models, so easy to compute due to their parametric description. These models are called heuristic, as being based on experimental measurements in controlled environments. These have been formulated to describe the backscattering properties of irregularly shaped marine sand or flocs suspensions following a:math:`1/4\\Phi` size distribution. The class calls the method :func:`hydrac.model.scattering.scattering.Scattering.calc_f` to compute the model for all :math:`ka` values. Parameters ---------- obj : object Scattering object from :class:`hydrac.model.scattering.scattering.Scattering` f : float (numpy.array) Instrument frequencies a : float (numpy.array) Size vector theta : float Angle of observation (:math:`\\theta=0` for backscattering) """ def __init__(self, obj, f, a, theta=0): self.obj = obj self.obj.scattering.atmp = a self.obj.scattering.theta = theta self.obj.scattering.katmp = 2 * np.pi * np.outer(f, a) / self.obj.cw self.f = f if self.obj.particle.nature == 'MIN': # exec('self.obj.scattering.' + _modname[0] + # ',self.obj.scattering.' + _modname[1] + '=self.emp_min_func()') self.obj.scattering.f_inftmp,\ self.obj.scattering.c_inftmp = self.emp_min_func() elif self.obj.particle.nature == 'HYB': # exec('self.obj.scattering.' + _modname[0] + # ',self.obj.scattering.' + _modname[1] + '=self.emp_min_func()') self.obj.scattering.f_inftmp,\ self.obj.scattering.c_inftmp = self.emp_hyb_func() elif self.obj.particle.nature == 'ORG': self.obj.scattering.f_inftmp =\ np.zeros(np.shape(self.obj.scattering.katmp)) self.obj.scattering.c_inftmp =\ np.zeros(np.shape(self.obj.scattering.katmp))
[docs] def emp_min_func(self): """ This method computes the Thorne & Meral (2008) model. This model is only valid for backscattering, and describes the scattering properties of irregularly shaped marine sand Returns ------- f_inf : float (numpy.array) Model form function :math:`f_{\infty}` c_inf : float (numpy.array) Model total scattering cross-secton :math:`\\chi_{\infty}` """ kw = 1 / (self.obj.rho * self.obj.cw ** 2) kr = 1 / (self.obj.particle.param.rhos * self.obj.particle.param.c ** 2) etak = (kr-kw) / (kw) # etarho=3*(self.obj.particle.param.rhos-self.obj.water.paramw.rho)/... # ...(2*self.obj.particle.param.rhos+self.obj.water.paramw.rho) etarho = 3 * (self.obj.particle.param.rhos - self.obj.rho) / (2 * self.obj.particle.param.rhos + self.obj.rho) kf = (2 / 3) * np.abs(etak - etarho) kalph = (4 / 3) * (etak ** 2 + etarho ** 2 / 3) / 6 f_inf = np.array([[kf * row ** 2 * (1 - 0.25 * np.exp(-((row - 1.5) / 0.5) ** 2)) * (1 + 0.35 * np.exp(-((row - 2) / 2) ** 2)) / (1.13 + 0.8 * kf * row ** 2) for row in x] for x in self.obj.scattering.katmp]) c_inf = np.array([[kalph * row ** 4 / (1 + row ** 2 + 0.9 * kalph * row ** 4) for row in x] for x in self.obj.scattering.katmp]) return f_inf, c_inf
[docs] def emp_hyb_func(self): """ This method computes the Thorne et al. (2014) model. This model is only valid for backscattering, and describes the scattering properties of irregularly shaped marine and estuarine flocs Returns ------- f_inf : float (numpy.array) Model form function :math:`f_{\infty}` c_inf : float (numpy.array) Model total scattering cross-secton :math:`\\chi_{\infty}` """ # kw=1/(self.obj.water.paramw.rho*self.obj.water.paramw.cw**2) # kw=1/(self.obj.water.paramw.rho*self.obj.cw**2) co = self.obj.cw rho0 = self.obj.rho ck = np.sqrt(self.obj.particle.param.cp ** 2 - (4 / 3) * self.obj.particle.param.cs ** 2) rhok = self.obj.particle.param.rhos Co = 1 / (rho0 * co ** 2) Ck = 1 / (rhok * ck ** 2) gk = rhok / rho0 # hk = ck / co # effective density m = self.obj.particle.param.m Cf = self.obj.particle.param.Cf rhoex = list(Cf / (np.power(self.obj.scattering.atmp, m))) self.obj.particle.param.rhoex = rhoex self.obj.scattering.rhoex = rhoex kkk = 2 * np.pi * np.array(self.obj.scattering.freq) / co rhoex = Cf / (np.power(self.obj.scattering.katmp / kkk[0], m)) # gamma_o beta1 = 1.05 # zeta_o values beta2 = 1.05 # maximum physical value for effective density rhoex[np.where(rhoex > (rhok - rho0))] = rhok - rho0 # not letting effective density go below zero self.obj.scattering.update({'rhoex_param': Parameters({'m': self.obj.particle.param.m, 'Cf': self.obj.particle.param.Cf, 'beta1': beta1, 'beta2': beta2, 'rhok': rhok, 'rho0': rho0})}) rhoex[np.where(rhoex < 0)] = 0 g = 1 + rhoex / rho0 g[np.where(g < beta1)] = beta1 phi = (gk - g) / (gk - 1) # wood expression vw = ((phi * rho0 + (1 - phi) * rhok) * (phi * Co + (1 - phi) * Ck)) ** (- 0.5) h = vw / co h[np.where(h < beta2)] = beta2 e = g * h ** 2 kf = 2 * np.abs((e - 1) / (3 * e) + (g - 1) / (2 * g + 1)) alpha1 = 1.2 f_inf = np.array([coef * row ** 2 / (1 + alpha1 * row ** 2) for coef, row in zip(list(kf), list(self.obj.scattering.katmp) )]) kalfa = 2 * (((e - 1) / (3 * e)) ** 2 + (1 / 3) * ((g - 1) / (2 * g + 1)) ** 2) c_inf_tmp = np.array([coef * row ** 4 / (1 - 1.0 * row + 1.5 * row ** 2 + coef * row ** 4) for coef, row in zip(list(kalfa), list(self.obj.scattering.katmp))]) # viscous atten # chi_hs scattering rho = g v = 1e-6 w = 2 * np.pi * self.obj.scattering.freq[0] k = w / co beta = np.sqrt(w / (2 * v)) pro = beta * self.obj.scattering.katmp / kkk[0] delta = 0.5 * (1 + (9 / (2 * pro))) s = (9 / (4 * pro)) * (1 + (1 / (pro))) e1 = ((k * (rho - 1) ** 2) / 2) e2 = s / (s ** 2 + (rho + delta) ** 2) # converted to chi_hv values e12 = e1 * e2 chiv = (4 * (self.obj.scattering.katmp / kkk[0]) / 3) * e12 # combine scat and visc atten chi_h c_inf = c_inf_tmp + chiv return f_inf, c_inf