def ellipse(locs, mesh, scale=1.0, rotation=None): r""" Ellipse indicator function associated with a list of region of interest tuples. Takes the value `scale` in the region ..math:: (x - x_0)^2/r_x^2 + (y - y_0)^2/r_y^2 < 1 and zero elsewhere. Similarly for other dimensions. :kwarg scale: scale factor for indicator. :kwarg rotation: angle by which to rotate. """ d = mesh.topological_dimension() dims, L = range(d), range(len(locs)) # Itersets x = SpatialCoordinate(mesh) # Get distances from origins and RHS values X = [[x[i] - locs[j][i] for i in dims] for j in L] r = [[ locs[j][d] if len(locs[j]) == d + 1 else locs[j][d + i] for i in dims ] for j in L] # Apply rotations if rotation is not None: rotate(X, rotation) # Combine to get indicator conditions = [lt(sum((X[j][i] / r[j][i])**2 for i in dims), 1) for j in L] return conditional(combine(Or, *conditions), scale, 0)
def box(locs, mesh, scale=1.0, rotation=None): r""" Rectangular indicator functions associated with a list of region of interest tuples. Takes the value `scale` in the region ..math:: (|x - x0| < r_x) && (|y - y0| < r_y) centred about (x0, y0) and zero elsewhere. Similarly for other dimensions. :kwarg scale: scale factor for indicator. :kwarg rotation: angle by which to rotate. """ d = mesh.topological_dimension() dims, L = range(d), range(len(locs)) # Itersets x = SpatialCoordinate(mesh) # Get distances from origins and RHS values X = [[x[i] - locs[j][i] for i in dims] for j in L] r = [[ locs[j][d] if len(locs[j]) == d + 1 else locs[j][d + i] for i in dims ] for j in L] # Apply rotations if rotation is not None: rotate(X, rotation) # Combine to get indicator expr = [ combine(And, *[lt(abs(X[j][i]), r[j][i]) for i in dims]) for j in L ] return conditional(combine(Or, *expr), scale, 0.0)
def gaussian(locs, mesh, scale=1.0, rotation=None): r""" Gaussian bell associated with a list of region of interest tuples. Takes the form ..math:: \exp\left(- \left(\frac{x^2}{r_x^2} + \frac{y^2}{r_y^2}\right)\right) scaled by `scale` inside the ball region. Similarly for other dimensions. :kwarg scale: scale factor for indicator. :kwarg rotation: angle by which to rotate. """ d = mesh.topological_dimension() dims, L = range(d), range(len(locs)) # Itersets x = SpatialCoordinate(mesh) # Get distances from origins and RHS values X = [[x[i] - locs[j][i] for i in dims] for j in L] r = [[ locs[j][d] if len(locs[j]) == d + 1 else locs[j][d + i] for i in dims ] for j in L] # Apply rotations if rotation is not None: rotate(X, rotation) # Combine to get indicator q_sq = [sum((X[j][i] / r[j][i])**2 for i in dims) for j in L] # Quotient of squares # return sum(scale*conditional(lt(q_sq[j], 1), exp(-q_sq[j]), 0) for j in L) return sum(scale * exp(-q_sq[j]) for j in L)
def bump(locs, mesh, scale=1.0, rotation=None): r""" Rectangular bump function associated with a list of region of interest tuples. (A smooth approximation to the box function.) Takes the form ..math:: \exp\left(1 - \frac1{\left(1 - \left(\frac{x - x_0}{r_x}\right)^2\right)}\right) * \exp\left(1 - \frac1{\left(1 - \left(\frac{y - y_0}{r_y}\right)^2\right)}\right) scaled by `scale` inside the box region. Similarly for other dimensions. Note that we assume the provided regions are disjoint for this indicator. :kwarg scale: scale factor for indicator. :kwarg rotation: angle by which to rotate. """ d = mesh.topological_dimension() dims, L = range(d), range(len(locs)) # Itersets x = SpatialCoordinate(mesh) # Get distances from origins and RHS values X = [[x[i] - locs[j][i] for i in dims] for j in L] r = [[ locs[j][d] if len(locs[j]) == d + 1 else locs[j][d + i] for i in dims ] for j in L] # Apply rotations if rotation is not None: rotate(X, rotation) # Combine to get indicator q = [[(X[j][i] / r[j][i])**2 for i in dims] for j in L] # Quotients of squared distances conditions = [combine(And, *[lt(q[j][i], 1) for i in dims]) for j in L] bumps = [prod([exp(1 - 1 / (1 - q[j][i])) for i in dims]) for j in L] return sum([conditional(conditions[j], scale * bumps[j], 0) for j in L])
def circular_bump(locs, mesh, scale=1.0, rotation=None): r""" Circular bump function associated with a list of region of interest tuples. (A smooth approximation to the ball function.) Defining the radius :math:`r^2 := (x - x_0)^2 + (y - y_0)^2`, the circular bump takes the form ..math:: \exp\left(1 - \frac1{\left1 - \frac{r^2}{r_0^2}\right)}\right) scaled by `scale` inside the ball region. Similarly for other dimensions. :kwarg scale: scale factor for indicator. :kwarg rotation: angle by which to rotate. """ d = mesh.topological_dimension() dims, L = range(d), range(len(locs)) # Itersets x = SpatialCoordinate(mesh) # Get distances from origins and RHS values X = [[x[i] - locs[j][i] for i in dims] for j in L] r_sq = [[ locs[j][d]**2 if len(locs[j]) == d + 1 else locs[j][d + i]**2 for i in dims ] for j in L] # Apply rotations if rotation is not None: rotate(X, rotation) # Combine to get indicator q = [sum([X[j][i]**2 for i in dims]) / sum(r_sq[j]) for j in L] # Quotient of squared 2-norms return sum([ conditional(lt(q[j], 1), scale * exp(1 - 1 / (1 - q[j])), 0) for j in L ])