Source code for slippy.contact.lubricant
"""
A class for containing information about lubricants, allows the user to set sub models for the density etc,
should supply whatever is needed for the reynolds solver and the sub models/ other models in the lubricant
"""
import inspect
import typing
import warnings
from collections import OrderedDict
from slippy.core import _LubricantModelABC
from .lubricant_models import __all__ as built_in_models
from .lubricant_models import constant_array_property
__all__ = ['Lubricant']
[docs]class Lubricant(_LubricantModelABC):
"""A class for describing lubricant behaviours
Parameters
----------
name: str
The name of the lubricant, used for output and error messages
models: OrderedDict
The sub models to solve
constant_viscosity: float, optional (None)
The viscosity, should only be supplied if the viscosity is constant, otherwise an appropriate model should be
used. This adds both viscosity and nd_viscosity models.
constant_density: float, optional (None)
The density, should only be supplied if the density is constant, otherwise an appropriate model should be used.
This adds both density and nd_density models
Attributes
----------
sub_models: OrderedDict
The sub models which will be executed on each iteration of the reynolds solver
built_in_models: list
A list of all the named sub models built in to slippy, these are all available in slippy.contact.*model_name*
Methods
-------
Notes
-----
Examples
--------
"""
built_in_models = tuple(built_in_models)
[docs] def __init__(self, name: str, models: OrderedDict = None,
constant_viscosity: float = None, constant_density: float = None):
self.name = name
self.sub_models = OrderedDict()
if constant_viscosity is not None:
self.add_sub_model('viscosity', constant_array_property(constant_viscosity))
self.add_sub_model('nd_viscosity', constant_array_property(1.0))
if constant_density is not None:
self.add_sub_model('density', constant_array_property(constant_density))
self.add_sub_model('nd_density', constant_array_property(1.0))
if models is not None:
try:
for param, func in models.items():
self.add_sub_model(param, func)
except AttributeError:
raise TypeError('Models should be ordered dict of callable objects')
except TypeError:
raise TypeError('Models should be ordered dict of callable objects')
def add_sub_model(self, parameter: str, function: typing.Callable):
"""
Adds a lubricant sub model to be solved on each iteration of the solver
Parameters
----------
parameter: str
The name of the parameter found by the sub model, each sub model can only find one parameter
function: callable
The model function which will be called on each iteration of the solver. See notes for calling details
Notes
-----
The function will be called by passing the current model state dictionary to it as key word arguments. This
means that all models should:
- Accept the required keyword arguments
- Have no positional arguments
- Accept un used keyword arguments as **kwargs
The function can find any value but typically it will out put either a single value or a numpy array of values.
No additional parameters can be passed to the function when it is called (such as coefficients for a particular
fluid). This sort of parametrisation can be applied by passing a closure as the callable.
A list of the named sub models built in to slippy is available as the built_in_models attribute of this class.
Sub models will execute in the order they are added to this dict.
Examples
--------
#TODO
"""
# check that parameter is a string, with no spaces etc.
assert isinstance(parameter, str), 'Parameter name must be a string'
assert parameter.isidentifier(), 'Parameter name must be a valid variable name'
# check that function is callable
assert callable(function), 'Function must be callable'
# check that function has ** kwargs argument
full_arg_spec = inspect.getfullargspec(function)
assert full_arg_spec.varkw is not None, 'Function must accept a variable number of keyword arguments (**kwargs)'
# check that function has no positional only arguments
# warn if collision with existing sub model
if parameter in self.sub_models:
warnings.warn(f"Parameter {parameter} is already in sub models, this action has replaced the existing "
f"sub model")
# Add function to sub_models ordered dict
self.sub_models[parameter] = function
def data_check(self, current_state: set) -> set:
"""Use introspection to check that all sub models will solve properly
Parameters
----------
current_state: set
The state at the end of one iteration of the reynolds solver
Returns
-------
current_state: set
The updated current state with variables from the sub models
"""
for key, value in self.sub_models.items():
full_arg_spec = inspect.getfullargspec(value)
args = full_arg_spec.args
for arg in args:
if arg not in current_state and arg != 'self':
raise ValueError(f"Lubricant sub model {key} will not solve, requires {arg}, current state is "
f"{current_state}")
current_state.add(key)
return current_state
def solve_sub_models(self, current_state: dict) -> dict:
"""
Parameters
----------
current_state: dict
The current state of the model
Returns
-------
previous_state
"""
for parameter, func in self.sub_models.items():
current_state[parameter] = func(**current_state)
return current_state