def __init__(self, shape, obstacles, bc, stencil, Npml=15): self._shape = shape self._obstacles = obstacles self._check_obstacles() self._bc = bc self._stencil = stencil self._Npml = Npml self._nx, self._nz = shape self.dxdomains = Domain(shape) # For x derivatives self.dzdomains = Domain(shape) # For z derivatives self.fxdomains = Domain(shape) # For x filters self.fzdomains = Domain(shape) # For z filters self.adomains = Domain(shape) # For PMLs self.gdomain = Subdomain([0, 0, self._nx - 1, self._nz - 1], bc=self._bc, key=0, tag='g') # Indexes of the subdomains self._tnd = 0 self._tndx = 0 self._tndz = 0 # Initialize masks self._xmask, self._zmask = self.init_masks(shape, bc, obstacles) # Set up all Domain and Subdomain objects self._proceed()
def init_masks(shape, bc, obstacles): """ Init masks with obstacles. """ gdomain = Subdomain([0, 0, shape[0] - 1, shape[1] - 1], bc=bc) xmask = _np.zeros(shape, dtype=int) zmask = xmask.copy() for obs in obstacles: for mask in [xmask, zmask]: mask[obs.sx, obs.sz] = -1 mask[obs.sx, obs.iz] = -2 mask[obs.ix, obs.sz] = -2 for obs1, obs2 in _itertools.permutations(obstacles, r=2): c = obs1.intersection(obs2) if c: xmask[c[0], c[1]] = -1 zmask[c[0], c[1]] = -1 for obs in obstacles: coords = obs.touch(gdomain) if coords: for c in coords: xmask[c[0], c[1]] = -1 zmask[c[0], c[1]] = -1 _utils.remove_singles(xmask) _utils.remove_singles(zmask) return xmask, zmask
def _extrude_left(self, obs, idz): """ Extrude left wall of the obstacle. """ xc1, zc1 = obs.xz[0], idz[0] xc2, zc2 = obs.xz[0], idz[1] bc = '{}.{}.'.format(self._bc[0], obs.bc[0]) for i in range(xc1 - 1, -1, -1): xc2 = i mk = self._xmask[i, zc1 + 1:zc2] if _np.any(mk != 0): if _np.all(mk == -2): bc = 'W.{}.'.format(obs.bc[0]) elif _np.any(mk == -2): xc2 = int((xc1 + xc2) / 2 + 1) bc = 'X.{}.'.format(obs.bc[0]) elif _np.any(mk == 1): xc2 += 1 bc = 'X.{}.'.format(obs.bc[1]) break if abs(xc2 - xc1) < self._stencil: msg = _exceptions.CloseObstaclesError.msg.format( obs, self._stencil) raise _exceptions.CloseObstaclesError(msg) self._update_domains( Subdomain((xc2, zc1, xc1, zc2), bc, self._ndx, axis=0, tag='X'))
def _extrude_right(self, obs, idz): xc1, zc1 = obs.xz[2], idz[0] xc2, zc2 = obs.xz[2], idz[1] bc = '{}.{}.'.format(obs.bc[2], self._bc[2]) for i in range(xc1 + 1, self._nx): xc2 = i mk = self._xmask[i, zc1 + 1:zc2] if _np.any(mk != 0): if _np.all(mk != 0): bc = '{}.W.'.format(obs.bc[2]) elif _np.any(mk == -2): xc2 = int((xc1 + xc2) / 2 - 1) bc = '{}.X.'.format(obs.bc[2]) elif _np.any(mk == 1): xc2 -= 1 bc = '{}.X.'.format(obs.bc[1]) break if abs(xc2 - xc1) < self._stencil: msg = _exceptions.CloseObstaclesError.msg.format( obs, self._stencil) raise _exceptions.CloseObstaclesError(msg) self._update_domains( Subdomain((xc1, zc1, xc2, zc2), bc, self._ndx, axis=0, tag='X'))
def _extrude_bottom(self, obs, idx): """ Extrude bottom wall of the obstacle. """ xc1, zc1 = idx[0], obs.xz[1] xc2, zc2 = idx[1], obs.xz[1] bc = '.{}.{}'.format(self._bc[1], obs.bc[1]) for j in range(zc1 - 1, -1, -1): zc2 = j mk = self._zmask[xc1 + 1:xc2, j] if _np.any(mk != 0): if _np.all(mk == -2): bc = '.W.{}'.format(obs.bc[1]) elif _np.any(mk == -2): zc2 = int((zc1 + zc2) / 2 + 1) bc = '.X.{}'.format(obs.bc[1]) elif _np.any(mk == 1): zc2 += 1 bc = '.X.{}'.format(obs.bc[1]) break if abs(zc2 - zc1) < self._stencil: msg = _exceptions.CloseObstaclesError.msg.format( obs, self._stencil) raise _exceptions.CloseObstaclesError(msg) self._update_domains( Subdomain((xc1, zc2, xc2, zc1), bc, self._ndz, axis=1, tag='X'))
def _update_patches(self): """ Add patches. TODO : Fix 'else W' if an obstacle has another bc !""" for patch in _utils.find_areas(self._xmask, val=-2): bc = ['.', '.', '.', '.'] if patch[0] == 0: bc[0] = self._bc[0] else: bc[0] = 'X' if self._xmask[patch[0] - 1, patch[1]] == 1 else 'W' if patch[2] == self._nx - 1: bc[2] = self._bc[2] else: bc[2] = 'X' if self._xmask[patch[2] + 1, patch[1]] == 1 else 'W' self._update_domains( Subdomain(patch, axis=0, key=self._ndx, bc=''.join(bc), tag='W')) for patch in _utils.find_areas(self._zmask, val=-2): bc = ['.', '.', '.', '.'] if patch[1] == 0: bc[1] = self._bc[1] else: bc[1] = 'X' if self._xmask[patch[0], patch[1] - 1] == 1 else 'W' if patch[3] == self._nz - 1: bc[3] = self._bc[3] else: bc[3] = 'X' if self._xmask[patch[0], patch[3] + 1] == 1 else 'W' self._update_domains( Subdomain(patch, axis=1, key=self._ndz, bc=''.join(bc), tag='W'))
def _fill(self): """ Search remaining domains along both x and z axises. """ xmissings = _utils.find_areas(self._xmask, val=0) zmissings = _utils.find_areas(self._zmask, val=0) for c in xmissings: bc = ['X', '.', 'X', '.'] if c[0] == 0: bc[0] = self._bc[0] if c[2] == self._nx - 1: bc[2] = self._bc[2] self._update_domains( Subdomain(c, key=self._ndx, bc=''.join(bc), axis=0, tag='X')) for c in zmissings: bc = ['.', 'X', '.', 'X'] if c[1] == 0: bc[1] = self._bc[1] if c[3] == self._nz - 1: bc[3] = self._bc[3] self._update_domains( Subdomain(c, key=self._ndz, bc=''.join(bc), axis=1, tag='X'))
def _zbetween(self): """ Find domains between obstacles along z axis. """ idx = ComputationDomains.bounds(self._shape, self._bc, self._obstacles, axis=0) if idx: void = [(i[0], 0, i[1], self._nz - 1) for i in idx if i[2] == 'v'] void = _utils.remove_dups(void) for sub in void: self._update_domains( Subdomain(sub, '.{}.{}'.format(self._bc[1], self._bc[3]), self._ndz, axis=1, tag='X'))
def _xbetween(self): """ Find domains between obstacles along x axis. """ idz = ComputationDomains.bounds(self._shape, self._bc, self._obstacles, axis=1) if idz: void = [(0, i[0], self._nx - 1, i[1]) for i in idz if i[2] == 'v'] void = _utils.remove_dups(void) for sub in void: self._update_domains( Subdomain(sub, '{}.{}.'.format(self._bc[0], self._bc[2]), self._ndx, axis=0, tag='X'))