Exemplo n.º 1
0
 def divide_grid_and_radial2(self, v):
     gv, w = np.split(v, [self.grid_phys.N])
     g = np.zeros(self.grid.shape, v.dtype)
     g[self.phys] = gv
     w = self.v2r(w)
     out = EmbeddedFunction(self)
     out.load_data(g, w)
     return out
Exemplo n.º 2
0
 def __call__(self, f, **kwargs):
     """
     f must be of type EmbeddedFunction
     """
     _, fc, fr_list = f.get_components()
     # get the grid-based solution
     uch, uc = self._grid_solve(fc)
     # get interpolate method
     if self.interpolation_order == np.Inf:
         # get derivatives in Fourier space
         ucxh, ucyh = self.ikx * uch, self.iky * uch
         uch_stack = np.stack([uch, ucxh, ucyh])
         interpolater = periodic_interp2d(fh=uch_stack,
                                          eps=1e-14,
                                          upsampfac=1.25,
                                          spread_kerevalmeth=0)
         all_bvs = interpolater(self.ebdyc.interfaces_x_transf,
                                self.ebdyc.interfaces_y_transf)
         bvs = all_bvs[0].real
         bxs = all_bvs[1].real
         bys = all_bvs[2].real
     else:
         # interpolate the solution to the interface
         bvs = self.ebdyc.interpolate_grid_to_interface(
             uc, order=self.interpolation_order, cutoff=False)
         # get the grid solution's derivatives and interpolate to interface
         ucx, ucy = self.dx(uc), self.dy(uc)
         bxs = self.ebdyc.interpolate_grid_to_interface(
             ucx, order=self.interpolation_order, cutoff=False)
         bys = self.ebdyc.interpolate_grid_to_interface(
             ucy, order=self.interpolation_order, cutoff=False)
     # convert these from lists to vectors
     bvl, bxl, byl = self.ebdyc.v2l(bvs), self.ebdyc.v2l(
         bxs), self.ebdyc.v2l(bys)
     # compute the needed layer potentials
     sigmag_list = []
     for helper, fr, bv, bx, by in zip(self.helpers, fr_list, bvl, bxl,
                                       byl):
         sigmag_list.append(helper(fr, bv, bx, by, **kwargs))
     self.iteration_counts = [
         helper.iterations_last_call for helper in self.helpers
     ]
     # we now need to evaluate this onto the grid / interface points
     sigmag = np.concatenate(sigmag_list)
     out = self.evaluate_to_grid_pnai(sigmag)
     # need to divide this apart
     gu, bus = self.ebdyc.divide_pnai(out)
     # we can now add gu directly to uc
     uc[self.ebdyc.phys_not_in_annulus] += gu
     # we have to send the bslps back to the indivdual ebdys to deal with them
     urs = [helper.correct(bu) for helper, bu in zip(self.helpers, bus)]
     # interpolate urs onto uc
     _ = self.ebdyc.interpolate_radial_to_grid1(urs, uc)
     uc *= self.ebdyc.phys
     ue = EmbeddedFunction(self.ebdyc)
     ue.load_data(uc, urs)
     return ue
Exemplo n.º 3
0
 def gradient(self, ff, derivative_type='spectral'):
     """
     Compute the gradient of a function defined on the embedded boundary collection
     Inputs:
         ff, EmbeddedFunction: function to take the gradient of
         derivative_type: 'spectral' or 'fourth'
             in both cases, spectral differentation is used in the radial
             regions. On the grid, if 'spectral', then the function is cutoff
             and fourier based estimation of the derivative is used;
             if 'fourth', then the function is NOT cutoff and fourth-order
             centered differences are used.  This may provide better accuracy
             when the cutoff windows are thin.  However, if the cutoff windows
             are not at least 2h, then this can give catastrophically bad values
     Outputs:
         fx, fy: EmbeddedFunctions giving each required derivative
     """
     f, _, fr_list = ff.get_components()
     if derivative_type == 'spectral':
         fc = f * self.grid_step
         fc[self.ext] = 0.0
         fch = np.fft.fft2(fc)
         fxh = fch * self.ikx
         fyh = fch * self.iky
         fx = np.fft.ifft2(fxh).real
         fy = np.fft.ifft2(fyh).real
     else:
         fx = fd_x_4(f, self.grid.xh)
         fy = fd_y_4(f, self.grid.yh)
     # compute on the radial grid
     fxrs, fyrs = [], []
     for i in range(self.N):
         fxr, fyr = self[i].gradient(fx, fy, fr_list[i])
         fxrs.append(fxr)
         fyrs.append(fyr)
     # set to 0 on regular grid in the exterior region
     fx *= self.phys
     fy *= self.phys
     # generate EmbeddedFunctions
     ffx = EmbeddedFunction(self)
     ffy = EmbeddedFunction(self)
     ffx.load_data(fx, fxrs)
     ffy.load_data(fy, fyrs)
     return ffx, ffy
Exemplo n.º 4
0
 def laplacian(self, ff, derivative_type='spectral'):
     """
     Compute the laplacian of a function defined on the embedded boundary collection
     Inputs:
         ff, EmbeddedFunction: function to take the gradient of
         derivative_type: 'spectral' or 'fourth'
             in both cases, spectral differentation is used in the radial
             regions. On the grid, if 'spectral', then the function is cutoff
             and fourier based estimation of the derivative is used;
             if 'fourth', then the function is NOT cutoff and fourth-order
             centered differences are used.  This may provide better accuracy
             when the cutoff windows are thin.  However, if the cutoff windows
             are not at least 2h, then this can give catastrophically bad values
     Outputs:
         lapf: EmbeddedFunction giving the laplacian of f
     """
     f, _, fr_list = ff.get_components()
     if derivative_type == 'spectral':
         fc = f * self.grid_step
         fc[self.ext] = 0.0
         fch = np.fft.fft2(fc)
         lapfh = fch * self.lap
         lapf = np.fft.ifft2(lapfh).real
     else:
         fx = fd_x_4(f, self.grid.xh)
         fy = fd_y_4(f, self.grid.yh)
         fxx = fd_x_4(fx, self.grid.xh)
         fyy = fd_y_4(fy, self.grid.yh)
     # compute on the radial grid
     lapfrs = []
     for i in range(self.N):
         lapfr = self.ebdys[i].laplacian(lapf, fr_list[i])
         lapfrs.append(lapfr)
     # set to 0 on regular grid in the exterior region
     lapf *= self.phys
     # generate EmbeddedFunctions
     lapff = EmbeddedFunction(self)
     lapff.load_data(lapf, lapfrs)
     return lapff
Exemplo n.º 5
0
 def __call__(self, fu, fv, **kwargs):
     # separate the components
     fuc = fu.get_smoothed_grid_value()
     fvc = fv.get_smoothed_grid_value()
     fur_list = fu.get_radial_value_list()
     fvr_list = fv.get_radial_value_list()
     uc, vc, pc = self._grid_solve(fuc, fvc)
     # interpolate the solution to the interface
     bus = self.ebdyc.interpolate_grid_to_interface(
         uc, order=self.interpolation_order, cutoff=False)
     bvs = self.ebdyc.interpolate_grid_to_interface(
         vc, order=self.interpolation_order, cutoff=False)
     # get the grid solution's derivatives
     ucx, ucy = self.dx(uc), self.dy(uc)
     vcx, vcy = self.dx(vc), self.dy(vc)
     # compute the grid solutions stress
     tcxx = 2 * ucx - pc
     tcxy = ucy + vcx
     tcyy = 2 * vcy - pc
     # interpolate these to the interface
     btxxs = self.ebdyc.interpolate_grid_to_interface(
         tcxx, order=self.interpolation_order, cutoff=False)
     btxys = self.ebdyc.interpolate_grid_to_interface(
         tcxy, order=self.interpolation_order, cutoff=False)
     btyys = self.ebdyc.interpolate_grid_to_interface(
         tcyy, order=self.interpolation_order, cutoff=False)
     # convert these from lists to vectors
     bul, bvl = self.ebdyc.v2l(bus), self.ebdyc.v2l(bvs)
     btxxl, btxyl, btyyl = self.ebdyc.v2l(btxxs), self.ebdyc.v2l(
         btxys), self.ebdyc.v2l(btyys)
     # compute the needed layer potentials
     sigmag_list = []
     for helper, fur, fvr, bu, bv, btxx, btxy, btyy in zip(
             self.helpers, fur_list, fvr_list, bul, bvl, btxxl, btxyl,
             btyyl):
         sigmag_list.append(
             helper(fur, fvr, bu, bv, btxx, btxy, btyy, **kwargs))
     # we now need to evaluate this onto the grid / interface points
     sigmag = np.column_stack(sigmag_list)
     out = self.Layer_Apply(self.grid_sources, self.ebdyc.grid_pnai, sigmag)
     # need to divide this apart
     gu, bus = self.ebdyc.divide_pnai(out[0])
     gv, bvs = self.ebdyc.divide_pnai(out[1])
     gp, bps = self.ebdyc.divide_pnai(out[2])
     # we can now add gu directly to uc
     uc[self.ebdyc.phys_not_in_annulus] += gu
     vc[self.ebdyc.phys_not_in_annulus] += gv
     pc[self.ebdyc.phys_not_in_annulus] += gp
     # we have to send the bslps back to the indivdual ebdys to deal with them
     single_ebdy = len(self.ebdyc) == 1
     urs, vrs, prs = zip(*[
         helper.correct(bu, bv, bp, single_ebdy)
         for helper, bu, bv, bp in zip(self.helpers, bus, bvs, bps)
     ])
     # interpolate urs onto uc
     _ = self.ebdyc.interpolate_radial_to_grid1(urs, uc)
     _ = self.ebdyc.interpolate_radial_to_grid1(vrs, vc)
     _ = self.ebdyc.interpolate_radial_to_grid1(prs, pc)
     uc *= self.ebdyc.phys
     vc *= self.ebdyc.phys
     pc *= self.ebdyc.phys
     u = EmbeddedFunction(self.ebdyc)
     v = EmbeddedFunction(self.ebdyc)
     p = EmbeddedFunction(self.ebdyc)
     u.load_data(uc, urs)
     v.load_data(vc, vrs)
     p.load_data(pc, prs)
     return u, v, p
Exemplo n.º 6
0
fv = fv_function(grid.xg, grid.yg)
ua = u_function(grid.xg, grid.yg)
va = v_function(grid.xg, grid.yg)
fu_rs = [fu_function(ebdy.radial_x, ebdy.radial_y) for ebdy in ebdys]
fv_rs = [fv_function(ebdy.radial_x, ebdy.radial_y) for ebdy in ebdys]
ua_rs = [u_function(ebdy.radial_x, ebdy.radial_y) for ebdy in ebdys]
va_rs = [v_function(ebdy.radial_x, ebdy.radial_y) for ebdy in ebdys]
pa_rs = [p_function(ebdy.radial_x, ebdy.radial_y) for ebdy in ebdys]
pa_rs = [pa_r - np.mean(pa_r) for pa_r in pa_rs]
upper_u = np.concatenate(
    [u_function(ebdy.bdy.x, ebdy.bdy.y) for ebdy in ebdys])
upper_v = np.concatenate(
    [v_function(ebdy.bdy.x, ebdy.bdy.y) for ebdy in ebdys])

_fu = EmbeddedFunction(ebdyc)
_fu.load_data(fu, fu_rs)
fu = _fu
_fv = EmbeddedFunction(ebdyc)
_fv.load_data(fv, fv_rs)
fv = _fv

# setup the solver
solver = StokesSolver(ebdyc, solver_type=solver_type)
uc, vc, pc = solver(fu, fv, tol=1e-12, verbose=verbose)
ur = urs[0]
vr = vrs[0]

if plot:
    mue = np.ma.array(uc, mask=ebdyc.ext)
    fig, ax = plt.subplots()
    ax.pcolormesh(grid.xg, grid.yg, mue)