general cleanup and typing fixes
This commit is contained in:
parent
db9e7831b9
commit
f486209950
@ -44,6 +44,7 @@ def draw_polygons(self,
|
|||||||
# Turn surface_normal into its integer representation
|
# Turn surface_normal into its integer representation
|
||||||
if isinstance(surface_normal, Direction):
|
if isinstance(surface_normal, Direction):
|
||||||
surface_normal = surface_normal.value
|
surface_normal = surface_normal.value
|
||||||
|
assert(isinstance(surface_normal, int))
|
||||||
|
|
||||||
if surface_normal not in range(3):
|
if surface_normal not in range(3):
|
||||||
raise GridError('Invalid surface_normal direction')
|
raise GridError('Invalid surface_normal direction')
|
||||||
@ -96,8 +97,13 @@ def draw_polygons(self,
|
|||||||
# 3) Adjust polygons for center
|
# 3) Adjust polygons for center
|
||||||
polygons = [poly + center[surface] for poly in polygons]
|
polygons = [poly + center[surface] for poly in polygons]
|
||||||
|
|
||||||
|
# ## Generate weighing function
|
||||||
|
def to_3d(vector: numpy.ndarray, val: float = 0.0) -> numpy.ndarray:
|
||||||
|
v_2d = numpy.array(vector, dtype=float)
|
||||||
|
return numpy.insert(v_2d, surface_normal, (val,))
|
||||||
|
|
||||||
# iterate over grids
|
# iterate over grids
|
||||||
for (i, grid) in enumerate(self.grids):
|
for i, grid in enumerate(self.grids):
|
||||||
# ## Evaluate or expand eps[i]
|
# ## Evaluate or expand eps[i]
|
||||||
if callable(eps[i]):
|
if callable(eps[i]):
|
||||||
# meshgrid over the (shifted) domain
|
# meshgrid over the (shifted) domain
|
||||||
@ -105,17 +111,14 @@ def draw_polygons(self,
|
|||||||
(x0, y0, z0) = numpy.meshgrid(*domain, indexing='ij')
|
(x0, y0, z0) = numpy.meshgrid(*domain, indexing='ij')
|
||||||
|
|
||||||
# evaluate on the meshgrid
|
# evaluate on the meshgrid
|
||||||
eps[i] = eps[i](x0, y0, z0)
|
eps_i = eps[i](x0, y0, z0)
|
||||||
if not numpy.isfinite(eps[i]).all():
|
if not numpy.isfinite(eps_i).all():
|
||||||
raise GridError('Non-finite values in eps[%u]' % i)
|
raise GridError('Non-finite values in eps[%u]' % i)
|
||||||
elif not is_scalar(eps[i]):
|
elif not is_scalar(eps[i]):
|
||||||
raise GridError('Unsupported eps[{}]: {}'.format(i, type(eps[i])))
|
raise GridError('Unsupported eps[{}]: {}'.format(i, type(eps[i])))
|
||||||
# do nothing if eps[i] is scalar non-callable
|
else:
|
||||||
|
# eps[i] is scalar non-callable
|
||||||
# ## Generate weighing function
|
eps_i = eps[i]
|
||||||
def to_3d(vector: List or numpy.ndarray, val: float=0.0):
|
|
||||||
v_2d = numpy.array(vector, dtype=float)
|
|
||||||
return numpy.insert(v_2d, surface_normal, (val,))
|
|
||||||
|
|
||||||
w_xy = zeros((bdi_max - bdi_min + 1)[surface].astype(int))
|
w_xy = zeros((bdi_max - bdi_min + 1)[surface].astype(int))
|
||||||
|
|
||||||
@ -183,7 +186,7 @@ def draw_polygons(self,
|
|||||||
|
|
||||||
# ## Modify the grid
|
# ## Modify the grid
|
||||||
g_slice = (i,) + tuple(numpy.s_[bdi_min[a]:bdi_max[a] + 1] for a in range(3))
|
g_slice = (i,) + tuple(numpy.s_[bdi_min[a]:bdi_max[a] + 1] for a in range(3))
|
||||||
self.grids[g_slice] = (1 - w) * self.grids[g_slice] + w * eps[i]
|
self.grids[g_slice] = (1 - w) * self.grids[g_slice] + w * eps_i
|
||||||
|
|
||||||
|
|
||||||
def draw_polygon(self,
|
def draw_polygon(self,
|
||||||
@ -327,11 +330,9 @@ def draw_extrude_rectangle(self,
|
|||||||
# Turn extrude_direction into its integer representation
|
# Turn extrude_direction into its integer representation
|
||||||
if isinstance(direction, Direction):
|
if isinstance(direction, Direction):
|
||||||
direction = direction.value
|
direction = direction.value
|
||||||
if abs(direction) not in range(3):
|
assert(isinstance(direction, int))
|
||||||
raise GridError('Invalid extrude_direction')
|
|
||||||
|
|
||||||
s = numpy.sign(polarity)
|
s = numpy.sign(polarity)
|
||||||
surface = numpy.delete(range(3), direction)
|
|
||||||
|
|
||||||
rectangle = numpy.array(rectangle, dtype=float)
|
rectangle = numpy.array(rectangle, dtype=float)
|
||||||
if s == 0:
|
if s == 0:
|
||||||
@ -344,12 +345,14 @@ def draw_extrude_rectangle(self,
|
|||||||
center = rectangle.sum(axis=0) / 2.0
|
center = rectangle.sum(axis=0) / 2.0
|
||||||
center[direction] += s * distance / 2.0
|
center[direction] += s * distance / 2.0
|
||||||
|
|
||||||
|
surface = numpy.delete(range(3), direction)
|
||||||
|
|
||||||
dim = numpy.fabs(diff(rectangle, axis=0).T)[surface]
|
dim = numpy.fabs(diff(rectangle, axis=0).T)[surface]
|
||||||
p = numpy.vstack((numpy.array([-1, -1, 1, 1], dtype=float) * dim[0]/2.0,
|
p = numpy.vstack((numpy.array([-1, -1, 1, 1], dtype=float) * dim[0]/2.0,
|
||||||
numpy.array([-1, 1, 1, -1], dtype=float) * dim[1]/2.0)).T
|
numpy.array([-1, 1, 1, -1], dtype=float) * dim[1]/2.0)).T
|
||||||
thickness = distance
|
thickness = distance
|
||||||
|
|
||||||
eps_func = [None] * len(self.grids)
|
eps_func = []
|
||||||
for i, grid in enumerate(self.grids):
|
for i, grid in enumerate(self.grids):
|
||||||
z = self.pos2ind(rectangle[0, :], i, round_ind=False, check_bounds=False)[direction]
|
z = self.pos2ind(rectangle[0, :], i, round_ind=False, check_bounds=False)[direction]
|
||||||
|
|
||||||
@ -367,10 +370,10 @@ def draw_extrude_rectangle(self,
|
|||||||
xyzi = numpy.array([self.pos2ind(qrs, which_shifts=i)
|
xyzi = numpy.array([self.pos2ind(qrs, which_shifts=i)
|
||||||
for qrs in zip(xs.flat, ys.flat, zs.flat)], dtype=int)
|
for qrs in zip(xs.flat, ys.flat, zs.flat)], dtype=int)
|
||||||
# reshape to original shape and keep only in-plane components
|
# reshape to original shape and keep only in-plane components
|
||||||
(qi, ri) = [numpy.reshape(xyzi[:, k], xs.shape) for k in surface]
|
qi, ri = (numpy.reshape(xyzi[:, k], xs.shape) for k in surface)
|
||||||
return eps[qi, ri]
|
return eps[qi, ri]
|
||||||
|
|
||||||
eps_func[i] = f_eps
|
eps_func.append(f_eps)
|
||||||
|
|
||||||
self.draw_polygon(direction, center, p, thickness, eps_func)
|
self.draw_polygon(direction, center, p, thickness, eps_func)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ __author__ = 'Jan Petykiewicz'
|
|||||||
eps_callable_type = Callable[[numpy.ndarray, numpy.ndarray, numpy.ndarray], numpy.ndarray]
|
eps_callable_type = Callable[[numpy.ndarray, numpy.ndarray, numpy.ndarray], numpy.ndarray]
|
||||||
|
|
||||||
|
|
||||||
class Grid(object):
|
class Grid:
|
||||||
"""
|
"""
|
||||||
Simulation grid generator intended for electromagnetic simulations.
|
Simulation grid generator intended for electromagnetic simulations.
|
||||||
Can be used to generate non-uniform rectangular grids (the entire grid
|
Can be used to generate non-uniform rectangular grids (the entire grid
|
||||||
@ -44,19 +44,32 @@ class Grid(object):
|
|||||||
Because of this, we either assume this 'ghost' cell is the same size as the last
|
Because of this, we either assume this 'ghost' cell is the same size as the last
|
||||||
real cell, or, if `self.periodic[a]` is set to `True`, the same size as the first cell.
|
real cell, or, if `self.periodic[a]` is set to `True`, the same size as the first cell.
|
||||||
"""
|
"""
|
||||||
|
exyz: List[numpy.ndarray]
|
||||||
|
"""Cell edges. Monotonically increasing without duplicates."""
|
||||||
|
|
||||||
Yee_Shifts_E = 0.5 * numpy.array([[1, 0, 0],
|
grids: numpy.ndarray
|
||||||
|
"""epsilon (or mu, or whatever) grids. shape is (num_grids, X, Y, Z)"""
|
||||||
|
|
||||||
|
periodic: List[bool]
|
||||||
|
"""For each axis, determines how far the rightmost boundary gets shifted. """
|
||||||
|
|
||||||
|
shifts: numpy.ndarray
|
||||||
|
"""Offsets `[[x0, y0, z0], [x1, y1, z1], ...]` for grid `0,1,...`"""
|
||||||
|
|
||||||
|
Yee_Shifts_E: ClassVar[numpy.ndarray] = 0.5 * numpy.array([[1, 0, 0],
|
||||||
[0, 1, 0],
|
[0, 1, 0],
|
||||||
[0, 0, 1]], dtype=float) # type: numpy.ndarray
|
[0, 0, 1]], dtype=float)
|
||||||
"""Default shifts for Yee grid E-field"""
|
"""Default shifts for Yee grid E-field"""
|
||||||
|
|
||||||
Yee_Shifts_H = 0.5 * numpy.array([[0, 1, 1],
|
Yee_Shifts_H: ClassVar[numpy.ndarray] = 0.5 * numpy.array([[0, 1, 1],
|
||||||
[1, 0, 1],
|
[1, 0, 1],
|
||||||
[1, 1, 0]], dtype=float) # type: numpy.ndarray
|
[1, 1, 0]], dtype=float)
|
||||||
"""Default shifts for Yee grid H-field"""
|
"""Default shifts for Yee grid H-field"""
|
||||||
|
|
||||||
from .draw import draw_polygons, draw_polygon, draw_slab, draw_cuboid, \
|
from .draw import (
|
||||||
draw_cylinder, draw_extrude_rectangle
|
draw_polygons, draw_polygon, draw_slab, draw_cuboid,
|
||||||
|
draw_cylinder, draw_extrude_rectangle,
|
||||||
|
)
|
||||||
from .read import get_slice, visualize_slice, visualize_isosurface
|
from .read import get_slice, visualize_slice, visualize_isosurface
|
||||||
from .position import ind2pos, pos2ind
|
from .position import ind2pos, pos2ind
|
||||||
|
|
||||||
@ -237,23 +250,17 @@ class Grid(object):
|
|||||||
Raises:
|
Raises:
|
||||||
`GridError` on invalid input
|
`GridError` on invalid input
|
||||||
"""
|
"""
|
||||||
self.exyz = [numpy.unique(pixel_edge_coordinates[i]) for i in range(3)] # type: List[numpy.ndarray]
|
self.exyz = [numpy.unique(pixel_edge_coordinates[i]) for i in range(3)]
|
||||||
"""Cell edges. Monotonically increasing without duplicates."""
|
self.shifts = numpy.array(shifts, dtype=float)
|
||||||
|
|
||||||
self.grids = None # type: numpy.ndarray
|
|
||||||
"""epsilon (or mu, or whatever) grids. shape is (num_grids, X, Y, Z)"""
|
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
if len(self.exyz[i]) != len(pixel_edge_coordinates[i]):
|
if len(self.exyz[i]) != len(pixel_edge_coordinates[i]):
|
||||||
warnings.warn('Dimension {} had duplicate edge coordinates'.format(i), stacklevel=2)
|
warnings.warn('Dimension {} had duplicate edge coordinates'.format(i), stacklevel=2)
|
||||||
|
|
||||||
if is_scalar(periodic):
|
if isinstance(periodic, bool):
|
||||||
periodic = [periodic] * 3
|
self.periodic = [periodic] * 3
|
||||||
self.periodic = periodic # type: List[bool]
|
else:
|
||||||
"""For each axis, determines how far the rightmost boundary gets shifted. """
|
self.periodic = list(periodic)
|
||||||
|
|
||||||
self.shifts = numpy.array(shifts, dtype=float) # type: numpy.ndarray
|
|
||||||
"""Offsets `[[x0, y0, z0], [x1, y1, z1], ...]` for grid `0,1,...`"""
|
|
||||||
|
|
||||||
if len(self.shifts.shape) != 2:
|
if len(self.shifts.shape) != 2:
|
||||||
raise GridError('Misshapen shifts: shifts must have two axes! '
|
raise GridError('Misshapen shifts: shifts must have two axes! '
|
||||||
@ -276,7 +283,7 @@ class Grid(object):
|
|||||||
raise GridError('Number of grids exceeds number of shifts (%u)' % num_shifts)
|
raise GridError('Number of grids exceeds number of shifts (%u)' % num_shifts)
|
||||||
|
|
||||||
grids_shape = hstack((num_grids, self.shape))
|
grids_shape = hstack((num_grids, self.shape))
|
||||||
if is_scalar(initial):
|
if isinstance(initial, (float, int)):
|
||||||
if isinstance(initial, int):
|
if isinstance(initial, int):
|
||||||
warnings.warn('Initial value is an int, grids will be integer-typed!', stacklevel=2)
|
warnings.warn('Initial value is an int, grids will be integer-typed!', stacklevel=2)
|
||||||
self.grids = numpy.full(grids_shape, initial)
|
self.grids = numpy.full(grids_shape, initial)
|
||||||
|
@ -42,7 +42,7 @@ def ind2pos(self,
|
|||||||
if check_bounds:
|
if check_bounds:
|
||||||
if round_ind:
|
if round_ind:
|
||||||
low_bound = 0.0
|
low_bound = 0.0
|
||||||
high_bound = -1
|
high_bound = -1.0
|
||||||
else:
|
else:
|
||||||
low_bound = -0.5
|
low_bound = -0.5
|
||||||
high_bound = -0.5
|
high_bound = -0.5
|
||||||
|
Loading…
Reference in New Issue
Block a user