Source code for stride.physics.boundaries.boundary


import numpy as np
from abc import ABC, abstractmethod


__all__ = ['Boundary']


[docs] class Boundary(ABC): """ Base class for Boundaries that can be applied to the different problem types. Parameters ---------- grid : DevitoGrid """ def __init__(self, grid): self._grid = grid
[docs] @abstractmethod def apply(self, *args, **kwargs): """ Generate the necessary pieces to make the boundary work. Returns ------- term Any extra terms to add to the equations. list Equations to execute before the state equation. list Equations to execute after the state equation. """ pass
[docs] def clear(self): """ Perform any clearing operations if needed. Returns ------- """ pass
[docs] def deallocate(self): """ Perform any deallocation operations if needed. Returns ------- """ pass
[docs] def damping(self, dimensions=None, damping_coefficient=None, mask=False, damping_type='sine', velocity=1.0, power_degree=2, reflection_coefficient=1e-3, assign=False, **kwargs): """ Create a damping field based on the dimensions of the grid. Parameters ---------- dimensions : tuple of ints, optional Whether or not to fill only certain dimensions, defaults to ``None``, all dimensions. damping_coefficient : float, optional Value of the maximum damping of the field. mask : bool, optional Create the damping layer as a mask (interior filled with ones) or not (interior filled with zeros). damping_type : str, optional Expression to be used for the shape of the damping function, defaults to ``sine``. velocity : ndarray or float, optional Velocity in the boundary region, defaults to 1.0. power_degree : int, optional Degree of the power to use for ``power`` damping, defaults to 2. reflection_coefficient : float, optional Theoretical reflection coefficient of the layer, defaults to 1e-3. assign : bool, optional Whether to assign or sum the value at each location, defaults to ``False``. Returns ------- ndarray Tensor containing the damping field. """ space = self._grid.space dimensions = tuple(range(space.dim)) if dimensions is None else dimensions # Create a damping field that corresponds to the given field, only scalar for now shape = np.array(space.extended_shape).take(dimensions) if mask: damp = np.ones(shape, dtype=np.float32) if damping_coefficient is not None: damp *= damping_coefficient else: damp = np.zeros(shape, dtype=np.float32) spacing = space.spacing absorbing = space.absorbing for dim_i, dimension in zip(range(len(dimensions)), dimensions): dimension_coefficient = damping_coefficient if dimension_coefficient is None: dimension_coefficient = (power_degree + 1) / 2 * np.log(1.0 / reflection_coefficient) dimension_coefficient = dimension_coefficient / (absorbing[dimension]*spacing[dimension]) \ if absorbing[dimension] > 15 else 0.67 / spacing[dimension] for index in range(absorbing[dimension]): # Damping coefficient pos = np.abs((absorbing[dimension] - index - 1) / float(absorbing[dimension] - 1)) if damping_type == 'sine': pos = pos - np.sin(2 * np.pi * pos) / (2 * np.pi) if mask: pos = - pos val = dimension_coefficient * pos elif damping_type == 'cosine': pos = np.cos(np.pi / 2 * (1 - pos)) if mask: pos = - pos val = pos elif damping_type == 'power': pos = pos**power_degree if mask: pos = - pos val = dimension_coefficient * pos else: raise ValueError('Allowed dumping type are (`sine`, `power`)') # : slices all_ind = [slice(index, s-index) for s in shape] # Left slice for dampening for dimension all_ind[dim_i] = slice(index, index + 1) if assign: damp[tuple(all_ind)] = val else: damp[tuple(all_ind)] += val # : slices all_ind = [slice(index, s-index) for s in shape] # right slice for dampening for dimension all_ind[dim_i] = slice(damp.shape[dim_i] - index - 1, damp.shape[dim_i] - index) if assign: damp[tuple(all_ind)] = val else: damp[tuple(all_ind)] += val if damping_coefficient is None: if damp.shape == velocity.shape: damp *= velocity else: damp *= np.max(velocity) return damp