### Example Usage of StaticStep Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/contact/static_step.html Demonstrates the setup and solving of a static contact model involving a round surface and a flat surface with different materials. This example shows how to define surfaces, materials, a contact model, and a static step, then solve the model. ```python import slippy.surface as s import slippy.contact as c # make surface geometry flat_surface = s.FlatSurface(shift=(0,0)) round_surface = s.RoundSurface((1,1,1), extent = (0.006, 0.006), shape = (255, 255), generate = True) # make and set materials steel = c.Elastic('Steel', {'E': 200e9, 'v':0.3}) aluminum = c.Elastic('Aluminum', {'E': 70e9, 'v':0.33}) flat_surface.material = aluminum round_surface.material = steel # make contact model my_model = c.ContactModel('model-1', round_surface, flat_surface) # make and add step total_load = 100 my_step = c.StaticStep('contact', normal_load=total_load, rtol_interference=1e-2) my_model.add_step(my_step) # solve the model result = my_model.solve() ``` -------------------------------- ### Install Jupyter Source: https://slippy.readthedocs.io/en/latest/_sources/examples.rst.txt Install Jupyter using pip. This is a prerequisite for running the example notebooks locally. ```shell python -m pip install jupyter ``` -------------------------------- ### Full Lubrication Contact Model Setup Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/contact/lubrication_steps.html This comprehensive example demonstrates the setup of a contact model involving a ball and a flat surface with a non-Newtonian lubricant. It includes Hertzian contact calculations, surface generation, material assignment, lubricant property definition, and the creation of a Reynolds solver and a contact step. ```python import slippy slippy.CUDA = False # Note: we are using a reynolds solver which does not currently support the CUDA back end import slippy.surface as s import slippy.contact as c radius = 0.01905 # The radius of the ball load = 800 # The load on the ball in N rolling_speed = 4 # The rolling speed in m/s (The mean speed of the surfaces) youngs_modulus = 200e9 # The youngs modulus of the surfaces p_ratio = 0.3 # The poission's ratio of the surfaces grid_size = 65 # The number of points in the descretisation grid eta_0 = 0.096 # Coefficient in the roelands pressure-viscosity equation roelands_p_0 = 1/5.1e-9# Coefficient in the roelands pressure-viscosity equation roelands_z = 0.68 # Coefficient in the roelands pressure-viscosity equation # Solving the hertzian contact to get the domain size and the initial guess hertz_result = c.hertz_full([radius, radius], [float('inf'), float('inf')], [youngs_modulus, youngs_modulus], [p_ratio, p_ratio], load) hertz_pressure = hertz_result['max_pressure'] hertz_a = hertz_result['contact_radii'][0] hertz_deflection = hertz_result['total_deflection'] hertz_pressure_function = hertz_result['pressure_f'] # make the surfaces ball = s.RoundSurface((radius,)*3, shape = (grid_size, grid_size), extent=(hertz_a*4,hertz_a*4), generate = True) flat = s.FlatSurface() # assigning materials steel = c.Elastic('steel', {'E' : youngs_modulus, 'v' : p_ratio}) ball.material = steel flat.material = steel # make the non newtonian fluid oil = c.Lubricant('oil') # Making a lubricant object to contain our sub models oil.add_sub_model('nd_viscosity', c.lubricant_models.nd_roelands(eta_0, roelands_p_0, hertz_pressure, roelands_z)) oil.add_sub_model('nd_density', c.lubricant_models.nd_dowson_higginson(hertz_pressure)) # make the contact model my_model = c.ContactModel('lubrication_test', ball, flat, oil) # make a reynolds solver reynolds = c.UnifiedReynoldsSolver(time_step = 0, grid_spacing = ball.grid_spacing, hertzian_pressure = hertz_pressure, radius_in_rolling_direction=radius, hertzian_half_width=hertz_a, dimentional_viscosity=eta_0, dimentional_density=872) # Find the hertzian pressure distribution as an initial guess X, Y = ball.get_points_from_extent() X, Y = X + ball._total_shift[0], Y + ball._total_shift[1] hertzian_pressure_dist = hertz_pressure_function(X, Y) # Making the step step = c.IterSemiSystem('main', reynolds, rolling_speed, 1, no_time=True, normal_load=load, initial_guess=[hertz_deflection, hertzian_pressure_dist], relaxation_factor=0.05, max_it_interference=3000) # Adding the step to the contact model my_model.add_step(step) # solve the model: state = my_model.solve() ``` -------------------------------- ### Example: Recreating Hertz Solution with StaticStep Source: https://slippy.readthedocs.io/en/latest/generated/slippy.contact.StaticStep.html This example demonstrates how to set up and solve a static contact problem, recreating the Hertz solution. It involves defining surfaces, materials, a contact model, and a StaticStep with a specified normal load. ```python >>> import slippy.surface as s >>> import slippy.contact as c >>> # make surface geometry >>> flat_surface = s.FlatSurface(shift=(0,0)) >>> round_surface = s.RoundSurface((1,1,1), extent = (0.006, 0.006), >>> shape = (255, 255), generate = True) >>> # make and set materials >>> steel = c.Elastic('Steel', {'E': 200e9, 'v':0.3}) >>> aluminum = c.Elastic('Aluminum', {'E': 70e9, 'v':0.33}) >>> flat_surface.material = aluminum >>> round_surface.material = steel >>> # make contact model >>> my_model = c.ContactModel('model-1', round_surface, flat_surface) >>> # make and add step >>> total_load = 100 >>> my_step = c.StaticStep('contact', normal_load=total_load, rtol_interference=1e-2) >>> my_model.add_step(my_step) >>> # solve the model >>> result = my_model.solve() ``` -------------------------------- ### DiscFreqSurface Initialization Example Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/FFTBased.html Instantiates a DiscFreqSurface with specified frequencies and amplitudes, sets the extent, and then discretizes the surface. ```python mySurf=DiscFreqSurface(10, 0.1) mySurf.extent=[0.5,0.5] mySurf.discretise(0.001) ``` -------------------------------- ### Run Jupyter Notebook Source: https://slippy.readthedocs.io/en/latest/_sources/examples.rst.txt Start the Jupyter Notebook server. This will open a notebook interface in your browser, allowing you to access and run example files. ```shell jupyter notebook ``` -------------------------------- ### Set Up Local Development Environment Source: https://slippy.readthedocs.io/en/latest/contributing.html Install SlipPY into a virtual environment for local development using python setup.py develop. ```bash $ mkvirtualenv slippy $ cd slippy/ $ python setup.py develop ``` -------------------------------- ### FlatSurface Example Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Geometric.html Demonstrates creating and using a FlatSurface with a specified slope. This is useful for simulating planar terrains. ```python >>> import numpy as np >>> my_surface=FlatSurface(slope=(1,1)) >>> x, y = np.arange(10), np.arange(10) >>> X, Y = np.meshgrid(x,y) >>> Z=my_surface.height(X, Y) ``` -------------------------------- ### Install SlipPY using Pip Source: https://slippy.readthedocs.io/en/latest/installation.html Once the virtual environment is activated, use this command to install SlipPY and its dependencies within that environment. ```bash python -m pip install slippy ``` -------------------------------- ### Install Slippy using Pip Source: https://slippy.readthedocs.io/en/latest/_sources/installation.rst.txt Once the virtual environment is activated, use this command to install Slippy and its dependencies within that environment. ```bash python -m pip install slippy ``` -------------------------------- ### RoundSurface Initialization Examples Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Geometric.html Shows how to initialize RoundSurface for different scenarios, including spherical and cylindrical surfaces, with options for extent, grid spacing, and rotation. ```python >>> import slippy.surface as s >>> my_surface = s.RoundSurface((1,1,1), extent=(0.5,0.5)) ``` ```python >>> my_surface = s.RoundSurface((1,float('inf'),1), extent=(0.5,0.5), grid_spacing=0.001, generate = True) ``` ```python >>> my_surface = s.RoundSurface((1,float('inf'),1), extent=(0.5, 0.5), shape=(512, 512), generate = True, >>> rotation=3.14/4) ``` -------------------------------- ### Quasi-Static Contact Modeling Example Source: https://slippy.readthedocs.io/en/latest/generated/slippy.contact.QuasiStaticStep.html This example demonstrates how to model the contact between a rough cylinder and a flat plane using slippy.contact.QuasiStaticStep. It covers defining surfaces, materials, creating a contact model, setting up the quasi-static step with specified parameters, adding output requests, and solving the model. This code can be used to generate load-displacement curves. ```python import slippy.surface as s import slippy.contact as c # define contact geometry cylinder = s.RoundSurface((1 ,np.inf, 1), shape=(256, 256), grid_spacing=0.001) roughness = s.HurstFractalSurface(1, 0.2, 1000, shape=(256, 256), grid_spacing=0.001, generate = True) combined = cylinder + roughness * 0.00001 flat = s.FlatSurface(shape=(256, 256), grid_spacing=0.001, generate = True) # define material behaviour and assign to surfaces material = c.Elastic('steel', properties = {'E':200e9, 'v':0.3}) combined.material = material flat.material = material # make a contact model my_model = c.ContactModel('qss_test', combined, flat) # make a modelling step to describe the problem max_int = 0.002 n_time_steps = 20 my_step = c.QuasiStaticStep('loading', n_time_steps, no_time=True, interference = [max_int*0.001, max_int], periodic_geometry=True, periodic_axes = (False, True)) # add the steps to the model my_model.add_step(my_step) # add output requests output_request = c.OutputRequest('Output-1', ['interference', 'total_normal_load', 'loads_z', 'total_displacement', 'converged']) my_step.add_output(output_request) # solve the model final_result = my_model.solve() ``` -------------------------------- ### Create and Discretize a Hurst Fractal Surface Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/FFTBased.html Example of creating a HurstFractalSurface object with specified fractal parameters and then discretizing it to generate a surface profile. The show() method is called to visualize the generated surface. ```python my_surface=HurstFractalSurface(1,0.2,1000, shape=(128, 128), grid_spacing=0.01) my_surface.discretise() my_surface.show() ``` -------------------------------- ### Elastic Material Model Example Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/core/elastic_material.html Demonstrates how to create an Elastic material model for steel and retrieve its properties like p-wave modulus and speed of sound. Requires the 'numpy' library. ```python import numpy as np from slippy.core.elastic_material import Elastic # Make a material model for elastic steel steel = Elastic('steel', {'E': 200e9, 'v': 0.3}) # Find it's p-wave modulus: pwm = steel.M # Find the speeds of sound: sos = steel.speed_of_sound(7890) ``` -------------------------------- ### _ArrayReader Initialization and Usage Example Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/core/outputs.html Demonstrates how to create and use an _ArrayReader object for lazily accessing array data stored within a zip file. It shows how to initialize the reader with file details and then access array properties like maximum value and individual elements. ```python >>> with OutputSaver('test') as output_files: >>> output_files.write({'my_array':np.array([1,2,3,4])}) >>> lazy_array = _ArrayReader('test.sar', '**array**#0#(4,)#int32') >>> # ^ file name in zip repo >>> # ^ shape of array >>> # ^ dtype of array >>> np.max(lazy_array) 4 >>> lazy_array[0] 1 ``` -------------------------------- ### Example Usage of alicona_read Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/alicona.html Demonstrates how to use the alicona_read function to load data from an .al3d file and display the depth data using matplotlib. ```python if __name__ == '__main__': file_name_t = "D:\\Downloads\\Alicona_data\\Surface Profile Data\\dem.al3d" from matplotlib.pyplot import imshow data_t = alicona_read(file_name_t) imshow(data_t['DepthData']) ``` -------------------------------- ### Rigid Material Initialization Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/core/materials.html Instantiates a Rigid material object with a given name. This is a basic setup for defining a rigid material within the system. ```python rigid = Rigid('rigid') ``` -------------------------------- ### QuasiStaticStep Initialization Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/contact/quasi_static_step.html Demonstrates the initialization of the QuasiStaticStep class with various parameters controlling the simulation behavior, such as time stepping, loading conditions, and numerical methods. ```python def __init__(self, step_name: str, number_of_steps: int, no_time: bool = False, time_period: float = 1.0, off_set_x: typing.Union[float, typing.Sequence[float]] = 0.0, off_set_y: typing.Union[float, typing.Sequence[float]] = 0.0, interference: typing.Union[float, typing.Sequence[float]] = None, normal_load: typing.Union[float, typing.Sequence[float]] = None, mean_gap: typing.Union[float, typing.Sequence[float]] = None, relative_loading: bool = False, adhesion: bool = True, unloading: bool = False, fast_ld: bool = False, impact_properties: dict = None, movement_interpolation_mode: str = 'linear', profile_interpolation_mode: str = 'nearest', periodic_geometry: bool = False, periodic_axes: tuple = (False, False), method: str = 'auto', max_it: int = 1000, tolerance=1e-8, max_it_outer: int = 100, tolerance_outer=1e-4, no_update_warning: bool = True, upper: float = 4.0): # movement interpolation mode sort out movement interpolation mode make array of values if impact_properties is not None: raise NotImplementedError("Impacts are not yet implemented") # work out the time step if needed: self._no_time = no_time self.total_time = time_period if not no_time and fast_ld: raise ValueError("Cannot have time dependence and fast_ld, either set no_time True or set fast_ld False") self._fast_ld = fast_ld self._relative_loading = relative_loading self.profile_interpolation_mode = profile_interpolation_mode self._periodic_profile = periodic_geometry self._periodic_axes = periodic_axes self._max_it_outer = max_it_outer self._r_tol_outer = tolerance_outer self._max_it = max_it self._r_tol = tolerance self.number_of_steps = int(round(number_of_steps)) if method not in {'auto', 'pk', 'double', 'rey'}: raise ValueError(f"Unrecognised method for step {step_name}: {method}") sum_param = (normal_load is not None) + (interference is not None) + (mean_gap is not None) if sum_param > 1 or sum_param == 0: raise ValueError(f"Exactly one of normal_load, interference and mean_gap must be set, {sum_param} were set") if mean_gap is not None: if method not in {'auto', 'rey'}: raise ValueError("pk and double methods don't support mean gap") else: method = 'rey' if interference is not None and method == 'rey': raise ValueError("Rey method doesn't support interference") self._method = method self._height_optimisation_func = None self._adhesion = adhesion self._unloading = unloading self._upper_factor = upper self.time_step = time_period / number_of_steps # check that something is actually changing self.update = set() ``` -------------------------------- ### Smooth Surface EHL with Non-Newtonian Fluid Example Source: https://slippy.readthedocs.io/en/latest/generated/slippy.contact.IterSemiSystem.html This example demonstrates setting up and solving an Elasto-Hydrodynamic Lubrication (EHL) contact with a non-Newtonian fluid using slippy.contact.IterSemiSystem. It includes defining surfaces, materials, lubricants with specific rheological models, and the iterative solver setup. ```python >>> import slippy >>> slippy.CUDA = False # Note: we are using a reynolds solver which does not currently support the CUDA back end >>> import slippy.surface as s >>> import slippy.contact as c >>> >>> radius = 0.01905 # The radius of the ball >>> load = 800 # The load on the ball in N >>> rolling_speed = 4 # The rolling speed in m/s (The mean speed of the surfaces) >>> youngs_modulus = 200e9 # The youngs modulus of the surfaces >>> p_ratio = 0.3 # The poission's ratio of the surfaces >>> grid_size = 65 # The number of points in the descretisation grid >>> eta_0 = 0.096 # Coefficient in the roelands pressure-viscosity equation >>> roelands_p_0 = 1/5.1e-9# Coefficient in the roelands pressure-viscosity equation >>> roelands_z = 0.68 # Coefficient in the roelands pressure-viscosity equation >>> >>> # Solving the hertzian contact to get the domain size and the initial guess >>> hertz_result = c.hertz_full([radius, radius], [float('inf'), float('inf')], >>> [youngs_modulus, youngs_modulus], >>> [p_ratio, p_ratio], load) >>> hertz_pressure = hertz_result['max_pressure'] >>> hertz_a = hertz_result['contact_radii'][0] >>> hertz_deflection = hertz_result['total_deflection'] >>> hertz_pressure_function = hertz_result['pressure_f'] >>> >>> # make the surfaces >>> ball = s.RoundSurface((radius,)*3, shape = (grid_size, grid_size), >>> extent=(hertz_a*4,hertz_a*4), generate = True) >>> flat = s.FlatSurface() >>> >>> # assigning materials >>> steel = c.Elastic('steel', {'E' : youngs_modulus, 'v' : p_ratio}) >>> ball.material = steel >>> flat.material = steel >>> >>> # make the non newtonian fluid >>> oil = c.Lubricant('oil') # Making a lubricant object to contain our sub models >>> oil.add_sub_model('nd_viscosity', c.lubricant_models.nd_roelands(eta_0, roelands_p_0, >>> hertz_pressure, roelands_z)) >>> oil.add_sub_model('nd_density', c.lubricant_models.nd_dowson_higginson(hertz_pressure)) >>> >>> # make the contact model >>> my_model = c.ContactModel('lubrication_test', ball, flat, oil) >>> >>> # make a reynolds solver >>> reynolds = c.UnifiedReynoldsSolver(time_step = 0, >>> grid_spacing = ball.grid_spacing, >>> hertzian_pressure = hertz_pressure, >>> radius_in_rolling_direction=radius, >>> hertzian_half_width=hertz_a, >>> dimentional_viscosity=eta_0, >>> dimentional_density=872) >>> >>> # Find the hertzian pressure distribution as an initial guess >>> X, Y = ball.get_points_from_extent() >>> X, Y = X + ball._total_shift[0], Y + ball._total_shift[1] >>> hertzian_pressure_dist = hertz_pressure_function(X, Y) >>> >>> # Making the step >>> step = c.IterSemiSystem('main', reynolds, rolling_speed, 1, no_time=True, normal_load=load, >>> initial_guess=[hertz_deflection, hertzian_pressure_dist], >>> relaxation_factor=0.05, max_it_interference=3000) >>> >>> # Adding the step to the contact model >>> my_model.add_step(step) >>> >>> # solve the model: >>> state = my_model.solve() ``` -------------------------------- ### Initialize Quasi-Static Step Parameters Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/contact/quasi_static_step.html Sets up initial conditions for quasi-static steps, including offsets, loads, and interference. Handles cases where parameters are functions of time or constant values. Raises errors for conflicting or insufficient input parameters. ```python if not isinstance(off_set_x, Number) or not isinstance(off_set_y, Number): if no_time: raise ValueError("Can not have no time dependence and sliding contact") off_set_x = [off_set_x] * 2 if isinstance(off_set_x, Number) else off_set_x off_set_y = [off_set_y] * 2 if isinstance(off_set_y, Number) else off_set_y off_set_x_func = make_interpolation_func(off_set_x, movement_interpolation_mode, 'relative_off_set_x') off_set_y_func = make_interpolation_func(off_set_y, movement_interpolation_mode, 'relative_off_set_y') self._off_set_upd = lambda time: np.array([off_set_y_func(time), off_set_x_func(time)]) self.update.add('off_set') self.off_set = None else: self.off_set = np.array([off_set_y, off_set_x]) if normal_load is not None and interference is not None: raise ValueError("Both normal_load and interference are set, only one of these can be set") if normal_load is None and interference is None: if relative_loading: interference = 0 else: raise ValueError("Cannot have no set load or interference and not relative loading, set either the" "normal load, normal interference or change relative_loading to True") self.load_controlled = False if normal_load is not None: if isinstance(normal_load, Number): self.normal_load = normal_load else: self.normal_load = None self._normal_load_upd = make_interpolation_func(normal_load, movement_interpolation_mode, 'normal_load') self.update.add('normal_load') self.load_controlled = True else: self.normal_load = None if mean_gap is not None: if isinstance(mean_gap, Number): self.mean_gap = mean_gap else: self.mean_gap = None self._mean_gap_upd = make_interpolation_func(mean_gap, movement_interpolation_mode, 'mean_gap') self.update.add('mean_gap') else: self.mean_gap = None if interference is not None: if isinstance(interference, Number): self.interference = interference else: self.interference = None self._interference_upd = make_interpolation_func(interference, movement_interpolation_mode, 'interference') self.update.add('interference') else: self.interference = None if not self.update and no_update_warning: warnings.warn("Nothing set to update") provides = {'off_set', 'loads_z', 'surface_1_displacement_z', 'surface_2_displacement_z', 'total_displacement_z', 'interference', 'just_touching_gap', 'surface_1_points', 'contact_nodes', 'surface_2_points', 'time', 'time_step', 'new_step', 'converged', 'gap', 'total_normal_load'} super().__init__(step_name, time_period, provides) ``` -------------------------------- ### Show Surface Profile as Image Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Surface_class.html Demonstrates how to display the surface profile as an image using the show method. Requires importing slippy.surface and numpy. ```python import slippy.surface as s import numpy as np my_surface=s.assurface(np.random.rand(10,10)) my_surface.show('profile', 'image') ``` -------------------------------- ### RandomFilterSurface.get_points_from_extent Source: https://slippy.readthedocs.io/en/latest/_sources/generated/slippy.surface.RandomFilterSurface.rst.txt Gets points from the surface extent. ```APIDOC ## RandomFilterSurface.get_points_from_extent ### Description Gets points from the surface extent. ### Method get_points_from_extent ### Parameters This method does not explicitly list parameters in the source documentation. ``` -------------------------------- ### RandomFilterSurface.get_height_of_mat_vr Source: https://slippy.readthedocs.io/en/latest/_sources/generated/slippy.surface.RandomFilterSurface.rst.txt Gets the height of the material volume (VR). ```APIDOC ## RandomFilterSurface.get_height_of_mat_vr ### Description Gets the height of the material volume (VR). ### Method get_height_of_mat_vr ### Parameters This method does not explicitly list parameters in the source documentation. ``` -------------------------------- ### get_summit_curvature Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Surface_class.html Gets summit curvatures. This method is an alias for the `slippy.surface.get_summit_curvature` function. ```APIDOC ## get_summit_curvature ### Description Gets summit curvatures. This method is an alias for the `slippy.surface.get_summit_curvature` function. ### Method `get_summit_curvature(self, summits=None, mask=None, filter_cut_off=None, four_nearest=False)` ### Parameters #### Path Parameters None #### Query Parameters * **summits** (array, optional) - The summits to calculate curvature for. If None, all summits are considered. * **mask** (array, optional) - The mask to apply to the surface. * **filter_cut_off** (float, optional) - The cut-off frequency for filtering. * **four_nearest** (bool, optional) - Whether to use the four nearest neighbors for calculations. ### Request Example None ### Response #### Success Response (200) Returns the summit curvatures. #### Response Example None ``` -------------------------------- ### ProbFreqSurface Initialization and Height Calculation Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/FFTBased.html Initializes a probabilistic frequency surface with parameters H, qr, and qs. The _height method generates a surface profile using FFT, calculating frequencies and variances based on input parameters and random normal distribution. ```python def __init__(self, h=2, qr=0.05, qs=10, generate: bool = False, grid_spacing: float = None, extent: tuple = None, shape: tuple = None): self.h = h self.qs = qs self.qr = qr super().__init__(grid_spacing=grid_spacing, extent=extent, shape=shape, generate=generate) def rotate(self, radians: Number): raise NotImplementedError("Probabilistic frequency surface cannot be rotated") def shift(self, shift: tuple = None): if shift is None: return raise NotImplementedError("Probabilistic frequency surface cannot be shifted") def _height(self, x_mesh, y_mesh): grid_spacing, extent, shape = check_coords_are_simple(x_mesh, y_mesh) qny = np.pi / grid_spacing u = np.linspace(0, qny, shape[0]) u_mesh, v_mesh = np.meshgrid(u, u) freqs = np.abs(u_mesh + v_mesh) varience = np.zeros(freqs.shape) varience[np.logical_and((1 / freqs) > (1 / self.qr), (2 * np.pi / freqs) <= (extent[0]))] = 1 varience[np.logical_and((1 / freqs) >= (1 / self.qs), (1 / freqs) < (1 / self.qr))] = \ (freqs[np.logical_and(1 / freqs >= 1 / self.qs, 1 / freqs < 1 / self.qr)] / self.qr) ** (-2 * (1 + self.h)) fou_trans = np.reshape(np.array([np.random.normal() * var ** 0.5 for var in varience.flatten()]), freqs.shape) return np.real(np.fft.ifft2(fou_trans)) def __repr__(self): string = self._repr_helper() return f'ProbFreqSurface(h={self.h}, qr={self.qr}, qs={self.qs}{string})' ``` -------------------------------- ### Surface Shape Property Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Surface_class.html Sets or gets the shape of the surface profile array. Cannot be set if a profile is already present. ```python @property def shape(self): """The shape of the surface profile array, the number of points in each direction """ return self._shape ``` ```python @shape.setter def shape(self, value: typing.Sequence[int]): if not isinstance(value, Sequence): raise ValueError(f"Shape should be a Sequence type, got: {type(value)}") if self._profile is not None: raise ValueError("Cannot set shape when profile is present") self._shape = tuple([int(x) for x in value]) self._size = np.product(self._shape) if self.grid_spacing is not None: self._extent = tuple([v * self.grid_spacing for v in value]) elif self.extent is not None: self._grid_spacing = self._extent[0] / self._shape[0] self._extent = tuple([sz * self.grid_spacing for sz in self.shape]) ``` ```python @shape.deleter def shape(self): if self.profile is None: self._shape = None self._size = None self._extent = None self._grid_spacing = None else: msg = "Cannot delete shape with a surface profile set" raise ValueError(msg) ``` -------------------------------- ### Create and Discretize HurstFractalSurface Source: https://slippy.readthedocs.io/en/latest/generated/slippy.surface.HurstFractalSurface.html Instantiates a HurstFractalSurface object with specified fractal parameters and then discretizes it over a defined grid. The 'show()' method is then called to visualize the generated surface. ```python >>> #create the surface object with the specified fractal parameters >>> my_surface=HurstFractalSurface(1,0.2,1000, shape=(128, 128), grid_spacing=0.01) >>> #descrtise the surface over a grid 1 unit by 1 unit with a grid_spacing of 0.01 >>> my_surface.discretise() >>> my_surface.show() ``` -------------------------------- ### grid_spacing property Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Surface_class.html Gets or sets the grid spacing of the surface. Handles type conversion and validation, and updates the surface extent accordingly. ```APIDOC ## `grid_spacing` property ### Description Manages the distance between grid points. When set, it validates the input, converts it to a float, and recalculates the surface extent based on the profile shape or vice versa. ### Getter Returns the current grid spacing. ### Setter ```python @grid_spacing.setter def grid_spacing(self, grid_spacing: float): # ... setter logic ... ``` #### Parameters * **grid_spacing** (float): The new grid spacing value. ### Deleter ```python @grid_spacing.deleter def grid_spacing(self): # ... deleter logic ... ``` #### Description Resets the grid spacing and extent to `None`. ``` -------------------------------- ### Surface Extent Property Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Surface_class.html Sets or gets the overall dimensions of the surface. Ensures aspect ratio consistency with the profile if the profile exists. ```python @property def extent(self): """ The overall dimensions of the surface in the same units as grid spacing """ return self._extent ``` ```python @extent.setter def extent(self, value: typing.Sequence[float]): if not isinstance(value, Sequence): msg = "Extent must be a Sequence, got {}".format(type(value)) raise TypeError(msg) if len(value) > 2: raise ValueError("Too many elements in extent, must be a maximum of two dimensions") if self.profile is not None: p_aspect = (self.shape[0]) / (self.shape[1]) e_aspect = value[0] / value[1] if abs(e_aspect - p_aspect) > 0.0001: msg = "Extent aspect ratio doesn't match profile aspect ratio" raise ValueError(msg) else: self._extent = tuple(value) self._grid_spacing = value[0] / (self.shape[0]) else: self._extent = tuple(value) self.dimensions = len(value) if self.grid_spacing is not None: self._shape = tuple([int(v / self.grid_spacing) for v in value]) self._size = np.product(self._shape) if self._shape is not None: self._grid_spacing = self._extent[0] / self._shape[0] self._extent = tuple([sz * self._grid_spacing for sz in self._shape]) return ``` ```python @extent.deleter def extent(self): self._extent = None self._grid_spacing = None if self.profile is None: self._shape = None self._size = None ``` -------------------------------- ### OutputRequest.__init__ Source: https://slippy.readthedocs.io/en/latest/_sources/generated/slippy.contact.OutputRequest.rst.txt Initializes a new instance of the OutputRequest class. ```APIDOC ## OutputRequest.__init__ ### Description Initializes a new instance of the OutputRequest class. ### Method __init__ ### Parameters (No parameters explicitly documented) ### Request Example (No request example provided) ### Response (No response details provided) ``` -------------------------------- ### Create and Configure Contact Model Step Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/contact/quasi_static_step.html Initializes a QuasiStaticStep for a contact model, specifying simulation parameters like maximum interference, number of time steps, and periodicity. ```python # make a contact model my_model = c.ContactModel('qss_test', combined, flat) # make a modelling step to describe the problem max_int = 0.002 n_time_steps = 20 my_step = c.QuasiStaticStep('loading', n_time_steps, no_time=True, interference = [max_int*0.001, max_int], periodic_geometry=True, periodic_axes = (False, True)) ``` -------------------------------- ### Get Summit Curvatures Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/roughness_funcs.html Calculates the curvatures of identified summits on a surface profile. Optionally finds summits if not provided and applies filtering. ```python def get_summit_curvatures(profile: np.ndarray, summits: typing.Optional[np.ndarray] = None, grid_spacing: float = None, mask: typing.Optional[typing.Union[np.ndarray, float]] = None, filter_cut_off: typing.Optional[float] = None, four_nearest: bool = False): """ find the curvatures of the summits Parameters ---------- profile: N by M array-like or Surface object The surface profile for analysis summits: N by M array (optional) A bool array True at the location of the summits, if not supplied the summits are found using find_summits first, see notes grid_spacing: float optional (False) The distance between points on the grid of the surface profile. Required only if the filter_cut_off is set and profile is not a surface object mask: array-like (bool)N by M or float optional (None) If an array, the array is used as a mask for the profile, must be the same shape as the profile, if a float is given, values which match are excluded from the calculation filter_cut_off: float, optional (None) The cutoff frequency of the low pass filter that is applied before finding summits four_nearest: bool, optional (False) If true a summit is found if it is higher than it's four nearest neighbours, else it must be higher than it's eight nearest neighbours Returns ------- curves : array Array of summit curvatures of size sum(summits.flatten()) Other parameters ---------------- four_nearest : bool optional (False) If true any point that is higher than it's 4 nearest neighbours will be counted as a summit, otherwise a point must be higher than it's 8 nearest neighbours to be a summit. Only used is summits are not given. filter_cut_off : float optional (None) If given the surface will be low pass filtered before finding summits. Only used if summits are not given See also -------- find_summits roughness Notes ----- If the summits parameter is not set, any key word arguments that can be passed to find_summits can be passed through this function. Examples -------- """ profile, grid_spacing = _check_surface(profile, grid_spacing) gs2 = grid_spacing ** 2 if summits is None: summits = find_summits(profile, filter_cut_off=filter_cut_off, grid_spacing=grid_spacing, four_nearest=four_nearest, mask=mask) verts = np.transpose(np.nonzero(summits)) curves = [-0.5 * (profile[vert[0] - 1, vert[1]] + profile[vert[0] + 1, vert[1]] + profile[vert[0], vert[1] - 1] + profile[vert[0], vert[1] + 1] - 4 * profile[vert[0], vert[1]]) / gs2 for vert in verts] return curves ``` -------------------------------- ### Create and Analyze Elastic Material Properties Source: https://slippy.readthedocs.io/en/latest/generated/slippy.contact.Elastic.html Demonstrates how to instantiate an Elastic material with its properties and retrieve derived values like the p-wave modulus and speed of sound. Requires density for speed of sound calculation. ```python >>> # Make a material model for elastic steel >>> steel = Elastic('steel', {'E': 200e9, 'v': 0.3}) >>> # Find it's p-wave modulus: >>> pwm = steel.M >>> # Find the speeds of sound: >>> sos = steel.speed_of_sound(7890) ``` -------------------------------- ### Quasi-Static Step Load Control Logic Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/contact/quasi_static_step.html Handles different solver methods ('pk', 'rey', or default) for load-controlled steps. Sets up bounds and calls the appropriate optimization function. ```python if self._method == 'pk': opt_func.contact_nodes = None opt_func.p_and_k(self.normal_load) elif self._method == 'rey': opt_func.contact_nodes = None opt_func.rey(target_load=self.normal_load) else: opt_func.change_load(self.normal_load, contact_nodes) # need to set bounds and pick a sensible starting point upper = self.upper print(f'upper bound set at: {upper}') if self._no_time: brackets = opt_func.get_bounds_from_cache(0, upper) else: brackets = (0, upper) print(f'Bounds adjusted using cache to: {brackets}') print(f'Interference tolerance set to {self._r_tol_outer} Relative') opt_func.brent(0, upper) # noinspection PyProtectedMember results = opt_func.results load_conv = (np.abs(results['total_normal_load'] - self.normal_load) / self.normal_load) < 0.05 results['converged'] = bool(load_conv) and not opt_func.last_call_failed return results ``` -------------------------------- ### Activate a Conda Virtual Environment Source: https://slippy.readthedocs.io/en/latest/_sources/installation.rst.txt Activate the previously created virtual environment to isolate package installations. The prompt will change to indicate the active environment. ```bash conda activate name_of_env ``` -------------------------------- ### QuasiStaticStep Constructor Source: https://slippy.readthedocs.io/en/latest/generated/slippy.contact.QuasiStaticStep.html Initializes a QuasiStaticStep object for quasi-static analysis. This constructor allows for detailed configuration of the simulation, including time stepping, interference, material properties, and geometric periodicity. ```APIDOC ## QuasiStaticStep Constructor ### Description Initializes a QuasiStaticStep object for quasi-static analysis. This constructor allows for detailed configuration of the simulation, including time stepping, interference, material properties, and geometric periodicity. ### Method __init__ ### Parameters - **_step_name** (str) - Required - The name of the step. - **_number_of_steps** (int) - Required - The total number of time steps for the simulation. - **_no_time** (bool) - Optional (default: False) - If True, time is not considered in the simulation. - **_time_period** (float) - Optional (default: 1.0) - The total time period for the simulation. - **_off_set_x** (Union[float, Sequence[float]]) - Optional (default: 0.0) - Offset in the x-direction. - **_off_set_y** (Union[float, Sequence[float]]) - Optional (default: 0.0) - Offset in the y-direction. - **_interference** (Optional[Union[float, Sequence[float]]]) - Optional (default: None) - The initial interference between bodies. - **_normal_load** (Optional[Union[float, Sequence[float]]]) - Optional (default: None) - The normal load applied to the bodies. - **_mean_gap** (Optional[Union[float, Sequence[float]]]) - Optional (default: None) - The mean gap between the bodies. - **_relative_loading** (bool) - Optional (default: False) - If True, loading is relative. - **_adhesion** (bool) - Optional (default: True) - If True, adhesion is considered. - **_unloading** (bool) - Optional (default: False) - If True, unloading is simulated. - **_fast_ld** (bool) - Optional (default: False) - If True, uses a faster loading/unloading method. - **_impact_properties** (Optional[dict]) - Optional (default: None) - Properties for impact simulation. - **_movement_interpolation_mode** (str) - Optional (default: 'linear') - Mode for interpolating movement. - **_profile_interpolation_mode** (str) - Optional (default: 'nearest') - Mode for interpolating profiles. - **_periodic_geometry** (bool) - Optional (default: False) - If True, the geometry is periodic. - **_periodic_axes** (tuple) - Optional (default: (False, False)) - Specifies the axes for periodicity. - **_method** (str) - Optional (default: 'auto') - The solution method to use. - **_max_it** (int) - Optional (default: 1000) - Maximum number of iterations for the solver. - **_tolerance** (float) - Optional (default: 1e-08) - Tolerance for the solver. - **_max_it_outer** (int) - Optional (default: 100) - Maximum number of outer iterations. - **_tolerance_outer** (float) - Optional (default: 0.0001) - Tolerance for outer iterations. - **_no_update_warning** (bool) - Optional (default: True) - Suppress warning if no movement or loading changes are specified. - **_upper** (float) - Optional (default: 4.0) - Upper bound factor for interference in load-controlled contact. ``` -------------------------------- ### Subtract profile ignoring NaN values Source: https://slippy.readthedocs.io/en/latest/generated/slippy.surface.subtract_polynomial.html This example demonstrates subtracting a polynomial from a profile while ignoring NaN height values by using a float mask. ```python flat_profile, coefs = subtract_polynomial(profile_2, 1, mask=float('nan')) ``` -------------------------------- ### RoundSurface Height Calculation Example Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Geometric.html Demonstrates calculating the height of a RoundSurface at specified points using its analytical height function. This is an alternative to discretizing the surface. ```python >>> import numpy as np >>> my_surface=RoundSurface(radius=(1,1,1)) >>> x, y = np.arange(10), np.arange(10) >>> x_mesh, y_mesh = np.meshgrid(x,y) >>> Z=my_surface.height(x_mesh, y_mesh) ``` -------------------------------- ### Initialize Surface Profile and Wear Volumes Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Surface_class.html Initializes the unworn and current surface profiles from a given value. It also sets up a defaultdict for tracking wear volumes, keyed by wear source names. ```python try: self.unworn_profile = np.asarray(value, dtype=float).copy() # this has to be before _profile is set (rewritten for rolling surface) self.wear_volumes = defaultdict(lambda: np.zeros_like(self.unworn_profile)) self._profile = np.asarray(value, dtype=float).copy() except ValueError: msg = "Could not convert profile to array of floats, profile contains invalid values" raise ValueError(msg) ``` -------------------------------- ### Analytical Surface Initialization Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/surface/Surface_class.html Initializes an analytical surface, optionally applying rotation and shift, and can generate the surface profile upon initialization. ```python def __init__(self, generate: bool = False, rotation: Number = None, shift: typing.Union[str, tuple] = None, grid_spacing: float = None, extent: tuple = None, shape: tuple = None): super().__init__(grid_spacing=grid_spacing, extent=extent, shape=shape) if rotation is not None: self.rotate(rotation) self.shift(shift) if generate: self.discretise() ``` -------------------------------- ### Instantiate and Discretize DiscFreqSurface Source: https://slippy.readthedocs.io/en/latest/generated/slippy.surface.DiscFreqSurface.html Instantiates a DiscFreqSurface with specified frequencies and amplitude, sets the extent, and then discretizes the surface with a given grid spacing. ```python >>> mySurf=DiscFreqSurface(10, 0.1) >>> mySurf.extent=[0.5,0.5] >>> mySurf.discretise(0.001) ``` -------------------------------- ### Perform Data Check on Model Source: https://slippy.readthedocs.io/en/latest/_modules/slippy/contact/models.html Initiates a data check for the entire model, printing the start time and model name, then sequentially checks each step. ```python def data_check(self): print("Data check started at:") print(datetime.now().strftime('%H:%M:%S %d-%m-%Y')) print(f"Checking model {self.name}:") self._model_check() current_state = None for this_step in self.steps: current_state = self.steps[this_step]._data_check(current_state) ```