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

"""
Main class that represents an oil record.

This maps to the JSON used in the DB

Having a Python class makes it easier to write importing, validating etc, code.
"""
from dataclasses import dataclass, field

from .validation.errors import ERRORS

from ..common.utilities import dataclass_to_json, JSON_List

from ..common.measurement import (Temperature,
                                  Density,
                                  DynamicViscosity,
                                  KinematicViscosity,
                                  AngularVelocity,
                                  InterfacialTension)


[docs]class RefTempList: """ mixin for all classes that are a list of points with reference temperatures """
[docs] def validate(self): """ validater for anything that has a list of reference temps e.g. density and viscosity For viscosity it checks for shear rate as well. """ points_list = self data_str = self.__class__.__name__ msgs = [] # check for odd temperatures for pt in points_list: if pt.ref_temp is None: msgs.append(ERRORS["E042"] .format(data_str + " reference temp")) return msgs temp = pt.ref_temp.converted_to('C').value if temp is None: msgs.append(ERRORS["E042"] .format(data_str + " reference temp")) return msgs if temp < -100.0: # arbitrary, but should catch K/C confusion t = f"{pt.ref_temp.value:.2f} {pt.ref_temp.unit}" msgs.append(ERRORS["E040"].format(data_str, t)) # check for duplicate temp/shear_rate combos temps = [] for p in points_list: temp = p.ref_temp.converted_to('K').value try: temp = temp + p.shear_rate.value except (TypeError, AttributeError): pass temps.append(temp) temps.sort() diff = (abs(t2 - t1) for t1, t2 in zip(temps[1:], temps[:1])) for d in diff: if d < 1e-3: msgs.append(ERRORS["E050"].format("Temperatures", data_str)) return msgs
[docs]@dataclass_to_json @dataclass class DensityPoint: density: Density = None ref_temp: Temperature = None method: str = None
[docs]class DensityList(JSON_List, RefTempList): item_type = DensityPoint
[docs]@dataclass_to_json @dataclass class DynamicViscosityPoint: viscosity: DynamicViscosity = None ref_temp: Temperature = None shear_rate: AngularVelocity = None method: str = None
[docs]class DynamicViscosityList(JSON_List, RefTempList): item_type = DynamicViscosityPoint
[docs]@dataclass_to_json @dataclass class KinematicViscosityPoint: viscosity: KinematicViscosity = None ref_temp: Temperature = None shear_rate: AngularVelocity = None method: str = None
[docs]class KinematicViscosityList(JSON_List, RefTempList): item_type = KinematicViscosityPoint
[docs]@dataclass_to_json @dataclass class PourPoint: measurement: Temperature = None method: str = None
[docs]@dataclass_to_json @dataclass class FlashPoint: measurement: Temperature = None method: str = None
[docs]@dataclass_to_json @dataclass class InterfacialTensionPoint: tension: InterfacialTension ref_temp: Temperature # interface: str = None # the interface is given in the attribute name method: str = None
[docs]class InterfacialTensionList(JSON_List, RefTempList): item_type = InterfacialTensionPoint
[docs]@dataclass_to_json @dataclass class PhysicalProperties: pour_point: PourPoint = None flash_point: FlashPoint = None densities: DensityList = field(default_factory=DensityList) kinematic_viscosities: KinematicViscosityList = field(default_factory=KinematicViscosityList) dynamic_viscosities: DynamicViscosityList = field(default_factory=DynamicViscosityList) interfacial_tension_air: InterfacialTensionList = field(default_factory=InterfacialTensionList) interfacial_tension_water: InterfacialTensionList = field(default_factory=InterfacialTensionList) interfacial_tension_seawater: InterfacialTensionList = field(default_factory=InterfacialTensionList)