Source code for opendrift.models.openoil.adios.oil

# This file is part of OpenDrift.
#
# OpenDrift is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 2
#
# OpenDrift is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OpenDrift.  If not, see <https://www.gnu.org/licenses/>.
#
# Copyright 2021, Gaute Hope, MET Norway
"""
Interface to the ADIOS oil database.
"""

import logging

logger = logging.getLogger(__name__)

import numpy as np
from typing import List

from adios_db.models.oil.oil import Oil as AdiosOil
from adios_db.computation import gnome_oil
from adios_db.computation import physical_properties
from adios_db.computation.estimations import oil_water_surface_tension_from_api


[docs] class NotFullOil(Exception): pass
[docs] def __require_gnome_oil__(f): def w(self, *args, **kwargs): if self.gnome_oil is None: raise NotFullOil() return f(self, *args, **kwargs) return w
[docs] class OpendriftOil: id: str type: str name: str API: float gnome_suitable: bool labels: List[str] location: str model_completeness: float product_type: str sample_date: str data: dict oil: AdiosOil gnome_oil: dict def __init__(self, o): self.data = o data = o meta = o['metadata'] self.id = o['oil_id'] self.name = o['metadata']['name'] #data = o['data'] #meta = data['attributes']['metadata'] #self.id = data['_id'] #self.name = meta['name'] logger.debug(f'Parsing Oil: {self.id} / {self.name}') #self.oil = AdiosOil.from_py_json(data['attributes']) self.oil = AdiosOil.from_py_json(data) if not self.oil.metadata.gnome_suitable: logger.error(f'{self.id} / {self.name}: is not GNOME suitable') else: self.gnome_oil = gnome_oil.make_gnome_oil(self.oil)
[docs] def __repr__(self): return f"[<adios.Oil> {self.id}] {self.name}"
[docs] def json(self): import json return json.dumps(self.data)
[docs] def make_full(self) -> 'OpendriftOil': return self
[docs] def valid(self): """ Check whether this oil can be used in Opendrift simulations. """ return self.oil.metadata.gnome_suitable
[docs] @__require_gnome_oil__ def density_at_temp(self, t, unit='K') -> float: """ Return density at temperature (in Kelvin by default). """ return physical_properties.Density(self.oil).at_temp(t, unit)
[docs] @__require_gnome_oil__ def kvis_at_temp(self, t, unit='K') -> float: return physical_properties.KinematicViscosity(self.oil).at_temp( t, temp_units=unit)
@property @__require_gnome_oil__ def mass_fraction(self) -> np.ndarray: return np.asarray(self.gnome_oil['mass_fraction'])
[docs] @__require_gnome_oil__ def oil_water_surface_tension(self) -> float: return oil_water_surface_tension_from_api(self.gnome_oil['api'])
@property @__require_gnome_oil__ def bulltime(self) -> float: bulltime = self.gnome_oil['bullwinkle_time'] if bulltime is None: return -999. # legacy from old oil_library else: return bulltime @property @__require_gnome_oil__ def bullwinkle(self) -> float: return self.gnome_oil['bullwinkle_fraction'] @property @__require_gnome_oil__ def emulsion_water_fraction_max(self) -> float: return self.gnome_oil['emulsion_water_fraction_max']
[docs] @__require_gnome_oil__ def vapor_pressure(self, temp) -> float: ''' Calculate vapor pressure. This method is taken from the old oil_library. Args: temp: temperature in Kelvin. Returns: Array of vapor pressures for each component. Pascal. ''' atmos_pressure = 101325.0 boiling_point = np.asarray(self.gnome_oil['boiling_point']) D_Zb = 0.97 R_cal = 1.987 # calories D_S = 8.75 + 1.987 * np.log(boiling_point) C_2i = 0.19 * boiling_point - 18 var = 1. / (boiling_point - C_2i) - 1. / (temp - C_2i) ln_Pi_Po = (D_S * (boiling_point - C_2i)**2 / (D_Zb * R_cal * boiling_point) * var) Pi = np.exp(ln_Pi_Po) * atmos_pressure return Pi
@property @__require_gnome_oil__ def molecular_weight(self): return np.asarray(self.gnome_oil['molecular_weight']) @property @__require_gnome_oil__ def k0y(self) -> float: return 2.024e-06 # Constant for all oils, should be checked
#return self.gnome_oil['k0y']