예제 #1
0
pad_zone = 0
verbose = True
plot = True
reparametrize = False
slepian_r = 1.5 * M
solver_type = 'spectral'  # fourth or spectral
coordinate_scheme = 'nufft'
coordinate_tolerance = 1e-14
qfs_tolerance = 1e-14

# get heaviside function
MOL = SlepianMollifier(slepian_r)
# construct boundary
bdy = GSB(c=star(nb, a=0.2, f=5))
if reparametrize:
    bdy = GSB(*arc_length_parameterize(bdy.x, bdy.y))
bh = bdy.dt * bdy.speed.min()
# get number of gridpoints to roughly match boundary spacing
ng = 2 * int(0.5 * 2.4 // bh)
# construct a grid
grid = Grid([-1.2, 1.2],
            ng, [-1.2, 1.2],
            ng,
            x_endpoints=[True, False],
            y_endpoints=[True, False])
# construct embedded boundary
ebdy = EmbeddedBoundary(bdy,
                        True,
                        M,
                        bh * 1,
                        pad_zone=pad_zone,
if ngx == ngy:
    xmin = -1.0
    xmax = 2.0
    ymin = -1.5
    ymax = ymin + (xmax - xmin)
else:
    xmin = -1.0
    xmax = 5.0
    ymin = -1.5
    ymax = ymin + (xmax - xmin) / 2

################################################################################
# Get truth via just using Adams-Bashforth 2 on periodic domain

bdy = GSB(c=star(nb, x=0.0, y=0.0, a=0.0, f=3))
bdy = GSB(*arc_length_parameterize(bdy.x, bdy.y))
bx = bdy.x
by = bdy.y

# generate a grid
xv, h = np.linspace(xmin, xmax, ngx, endpoint=False, retstep=True)
yv, _h = np.linspace(ymin, ymax, ngy, endpoint=False, retstep=True)
if _h != h:
    raise Exception('Need grid to be isotropic')
del _h
x, y = np.meshgrid(xv, yv, indexing='ij')
# fourier modes
kvx = np.fft.fftfreq(ngx, h / (2 * np.pi))
kvy = np.fft.fftfreq(ngy, h / (2 * np.pi))
kvx[int(ngx / 2)] = 0.0
kvy[int(ngy / 2)] = 0.0
예제 #3
0
M = 16
pad_zone = 0
verbose = False
plot = True
reparametrize = True
slepian_r = 2 * M
solver_type = 'spectral'  # fourth or spectral

# get heaviside function
MOL = SlepianMollifier(slepian_r)
# construct boundary
bdy1 = GSB(c=star(3 * nb, a=0.1, r=3, f=5))
bdy2 = GSB(c=squish(nb, x=-1.2, y=-0.7, b=0.4, rot=-np.pi / 4))
bdy3 = GSB(c=star(2 * nb, x=1, y=0.5, a=0.3, f=3))
if reparametrize:
    bdy1 = GSB(*arc_length_parameterize(bdy1.x, bdy1.y))
    bdy2 = GSB(*arc_length_parameterize(bdy2.x, bdy2.y))
    bdy3 = GSB(*arc_length_parameterize(bdy3.x, bdy3.y))
bh1 = bdy1.dt * bdy1.speed.min()
bh2 = bdy2.dt * bdy2.speed.min()
bh3 = bdy3.dt * bdy3.speed.min()
bh = min(bh1, bh2, bh3)
# get number of gridpoints to roughly match boundary spacing
ng = 2 * int(0.5 * 6.4 // bh)
# construct a grid
grid = Grid([-3.0, 3.4],
            ng, [-3.2, 3.2],
            ng,
            x_endpoints=[True, False],
            y_endpoints=[True, False])
# construct embedded boundary
예제 #4
0
    1 + np.cos(2 * np.pi * t))


# gradient function
def gradient(f):
    fh = np.fft.fft2(f)
    fx = np.fft.ifft2(fh * ikx).real
    fy = np.fft.ifft2(fh * iky).real
    return fx, fy


################################################################################
# Get truth via just using Forward Euler on periodic domain

bdy = GSB(c=star(nb, x=0.0, y=0.0, a=0.1, f=3))
bdy = GSB(*arc_length_parameterize(bdy.x, bdy.y))
bx = bdy.x
by = bdy.y

# generate a grid
v, h = np.linspace(-1.5, 1.5, ng, endpoint=False, retstep=True)
x, y = np.meshgrid(v, v, indexing='ij')
# fourier modes
kv = np.fft.fftfreq(ng, h / (2 * np.pi))
kv[int(ng / 2)] = 0.0
kx, ky = np.meshgrid(kv, kv, indexing='ij')
ikx, iky = 1j * kx, 1j * ky

# initial c field
c0 = c0_function(x, y)
예제 #5
0
    def generate(self, dt, fixed_grid=False):
        ebdyc = self.ebdyc
        ebdyc_old = self.ebdyc_old
        u, v = self.u, self.v
        uo, vo = self.uo, self.vo
        ux, uy, vx, vy = self.ux, self.uy, self.vx, self.vy
        uxo, uyo, vxo, vyo = self.uxo, self.uyo, self.vxo, self.vyo

        # interpolate the velocity
        ubs = ebdyc.interpolate_radial_to_boundary(u)
        vbs = ebdyc.interpolate_radial_to_boundary(v)

        # move all boundarys; generate new embedded boundaries
        new_ebdys = []
        self.reparmed_ubs = []
        self.reparmed_vbs = []
        for ind, ebdy in enumerate(self.ebdyc):
            if False:  # this is the ABF way
                # interpolate the velocity
                ub = ubs.bdy_value_list[ind]
                vb = vbs.bdy_value_list[ind]
                ubo_new_parm = self.ubos[ind]
                vbo_new_parm = self.vbos[ind]
                # move the boundary with Forward Euler
                bx = ebdy.bdy.x + 0.5 * dt * (3 * ub - ubo_new_parm)
                by = ebdy.bdy.y + 0.5 * dt * (3 * vb - vbo_new_parm)
                # repararmetrize the boundary
                bx, by, new_t = arc_length_parameterize(
                    bx,
                    by,
                    filter_fraction=self.filter_fraction,
                    return_t=True)
                # move these boundary values for velocity to the new parametrization
                self.reparmed_ubs.append(
                    nufft_interpolation1d(new_t, np.fft.fft(ub)))
                self.reparmed_vbs.append(
                    nufft_interpolation1d(new_t, np.fft.fft(vb)))
                # generate the new embedded boundary
                new_ebdy = ebdy.regenerate(bx, by)
                new_ebdys.append(new_ebdy)
            else:  # this is the BDF way
                # interpolate the velocity
                ub = ubs.bdy_value_list[ind]
                vb = vbs.bdy_value_list[ind]
                ubo_new_parm = self.ubos[ind]
                vbo_new_parm = self.vbos[ind]
                # move the boundary with Forward Euler
                bx = ebdy.bdy.x + 0.5 * dt * (3 * ub - ubo_new_parm)
                by = ebdy.bdy.y + 0.5 * dt * (3 * vb - vbo_new_parm)
                # repararmetrize the boundary
                bx, by, new_t = arc_length_parameterize(
                    bx,
                    by,
                    filter_fraction=self.filter_fraction,
                    return_t=True)
                # move these boundary values for velocity to the new parametrization
                self.reparmed_ubs.append(
                    nufft_interpolation1d(new_t, np.fft.fft(ub)))
                self.reparmed_vbs.append(
                    nufft_interpolation1d(new_t, np.fft.fft(vb)))
                # generate the new embedded boundary
                new_ebdy = ebdy.regenerate(bx, by)
                new_ebdys.append(new_ebdy)

        new_ebdyc = EmbeddedBoundaryCollection(new_ebdys)
        # get dnager zone distance
        umax = np.sqrt(u * u + v * v).max()
        ddd = 2 * umax * dt
        # raise an exception if danger zone thicker than radial width
        if ddd > new_ebdyc[0].radial_width:
            raise Exception(
                'Velocity is so fast that one timestep oversteps safety zones; reduce timestep.'
            )
        # register the grid...
        if fixed_grid:
            new_ebdyc.register_grid(ebdyc.grid, danger_zone_distance=ddd)
        else:
            new_ebdyc.generate_grid(danger_zone_distance=ddd)

        # let's get the points that need to be interpolated to
        aap = new_ebdyc.pnar
        AP_key = ebdyc.register_points(aap.x,
                                       aap.y,
                                       dzl=new_ebdyc.danger_zone_list,
                                       gil=new_ebdyc.guess_ind_list)
        OAP_key = ebdyc_old.register_points(aap.x,
                                            aap.y,
                                            dzl=new_ebdyc.danger_zone_list,
                                            gil=new_ebdyc.guess_ind_list)

        # now we need to interpolate onto things
        AEP = ebdyc.registered_partitions[AP_key]
        OAEP = ebdyc_old.registered_partitions[OAP_key]

        # get departure points
        xd_all = np.zeros(aap.N)
        yd_all = np.zeros(aap.N)
        xD_all = np.zeros(aap.N)
        yD_all = np.zeros(aap.N)

        # advect those in the annulus
        c1n, c2n, c3n = AEP.get_Ns()
        oc1n, oc2n, oc3n = OAEP.get_Ns()
        # category 1 and 2
        c1_2 = AEP.zone1_or_2
        oc1_2 = OAEP.zone1_or_2
        fc12 = np.logical_and(c1_2, oc1_2)
        fc12n = np.sum(fc12)

        # category 1 and 2
        # NOTE:  THESE INTERPOLATIONS CAN BE MADE FASTER BY EXPLOITING SHARED
        #        GRIDPOINTS IF THAT IS ENFORCED IN GRID GENERATION
        #        THIS IS NOT EXPLOITED, FOR THE TIME BEING
        uxh = ebdyc.interpolate_to_points(ux, aap.x, aap.y)
        uyh = ebdyc.interpolate_to_points(uy, aap.x, aap.y)
        vxh = ebdyc.interpolate_to_points(vx, aap.x, aap.y)
        vyh = ebdyc.interpolate_to_points(vy, aap.x, aap.y)
        uh = ebdyc.interpolate_to_points(u, aap.x, aap.y)
        vh = ebdyc.interpolate_to_points(v, aap.x, aap.y)

        uxoh = ebdyc_old.interpolate_to_points(uxo, aap.x, aap.y)
        uyoh = ebdyc_old.interpolate_to_points(uyo, aap.x, aap.y)
        vxoh = ebdyc_old.interpolate_to_points(vxo, aap.x, aap.y)
        vyoh = ebdyc_old.interpolate_to_points(vyo, aap.x, aap.y)
        uoh = ebdyc_old.interpolate_to_points(uo, aap.x, aap.y)
        voh = ebdyc_old.interpolate_to_points(vo, aap.x, aap.y)

        SLM = np.zeros([
            fc12n,
        ] + [4, 4], dtype=float)
        SLR = np.zeros([
            fc12n,
        ] + [
            4,
        ], dtype=float)

        # solve for departure points
        SLM[:, 0, 0] = uxh[fc12]
        SLM[:, 0, 1] = uyh[fc12]
        SLM[:, 0, 2] = 0.5 / dt
        SLM[:, 0, 3] = 0.0
        SLM[:, 1, 0] = vxh[fc12]
        SLM[:, 1, 1] = vyh[fc12]
        SLM[:, 1, 2] = 0.0
        SLM[:, 1, 3] = 0.5 / dt
        SLM[:, 2, 0] = 2.0 / dt + 3 * uxh[fc12]
        SLM[:, 2, 1] = 3 * uyh[fc12]
        SLM[:, 2, 2] = -uxoh[fc12]
        SLM[:, 2, 3] = -uyoh[fc12]
        SLM[:, 3, 0] = 3 * vxh[fc12]
        SLM[:, 3, 1] = 2.0 / dt + 3 * vyh[fc12]
        SLM[:, 3, 2] = -vxoh[fc12]
        SLM[:, 3, 3] = -vyoh[fc12]
        SLR[:, 0] = uh[fc12]
        SLR[:, 1] = vh[fc12]
        SLR[:, 2] = 3 * uh[fc12] - uoh[fc12]
        SLR[:, 3] = 3 * vh[fc12] - voh[fc12]
        OUT = np.linalg.solve(SLM, SLR)
        dx, dy, Dx, Dy = OUT[:, 0], OUT[:, 1], OUT[:, 2], OUT[:, 3]
        xd, yd = aap.x[fc12] - dx, aap.y[fc12] - dy
        xD, yD = aap.x[fc12] - Dx, aap.y[fc12] - Dy
        xd_all[fc12] = xd
        yd_all[fc12] = yd
        xD_all[fc12] = xD
        yD_all[fc12] = yD

        # categroy 3... this is the tricky one
        fc3n = aap.N - fc12n
        # print('Number of points in category 3 is:', fc3n)
        if fc3n > 0:
            for ind, (ebdy, ebdy_old) in enumerate(zip(ebdyc, ebdyc_old)):
                ub = ubs.bdy_value_list[ind]
                vb = vbs.bdy_value_list[ind]

                c3l = AEP.zone3l[ind]
                oc3l = OAEP.zone3l[ind]
                fc3l = np.unique(np.concatenate([c3l, oc3l]))
                th = ebdy.bdy.dt
                tk = ebdy.bdy.k

                def d1_der(f):
                    return np.fft.ifft(np.fft.fft(f) * tk * 1j).real

                interp = lambda f: interp1d(0, 2 * np.pi, th, f, k=3, p=True)
                bx_interp = interp(ebdy.bdy.x)
                by_interp = interp(ebdy.bdy.y)
                bxs_interp = interp(d1_der(ebdy.bdy.x))
                bys_interp = interp(d1_der(ebdy.bdy.y))
                nx_interp = interp(ebdy.bdy.normal_x)
                ny_interp = interp(ebdy.bdy.normal_y)
                nxs_interp = interp(d1_der(ebdy.bdy.normal_x))
                nys_interp = interp(d1_der(ebdy.bdy.normal_y))
                urb = ebdy.interpolate_radial_to_boundary_normal_derivative(
                    u[0])
                vrb = ebdy.interpolate_radial_to_boundary_normal_derivative(
                    v[0])
                urrb = ebdy.interpolate_radial_to_boundary_normal_derivative2(
                    u[0])
                vrrb = ebdy.interpolate_radial_to_boundary_normal_derivative2(
                    v[0])
                ub_interp = interp(ub)
                vb_interp = interp(vb)
                urb_interp = interp(urb)
                vrb_interp = interp(vrb)
                urrb_interp = interp(urrb)
                vrrb_interp = interp(vrrb)
                ubs_interp = interp(d1_der(ub))
                vbs_interp = interp(d1_der(vb))
                urbs_interp = interp(d1_der(urb))
                vrbs_interp = interp(d1_der(vrb))
                urrbs_interp = interp(d1_der(urrb))
                vrrbs_interp = interp(d1_der(vrrb))

                old_bx_interp = interp(ebdy_old.bdy.x)
                old_by_interp = interp(ebdy_old.bdy.y)
                old_bxs_interp = interp(d1_der(ebdy_old.bdy.x))
                old_bys_interp = interp(d1_der(ebdy_old.bdy.y))
                old_nx_interp = interp(ebdy_old.bdy.normal_x)
                old_ny_interp = interp(ebdy_old.bdy.normal_y)
                old_nxs_interp = interp(d1_der(ebdy_old.bdy.normal_x))
                old_nys_interp = interp(d1_der(ebdy_old.bdy.normal_y))
                old_ub = ebdy_old.interpolate_radial_to_boundary(uo[0])
                old_vb = ebdy_old.interpolate_radial_to_boundary(vo[0])
                old_urb = ebdy_old.interpolate_radial_to_boundary_normal_derivative(
                    uo[0])
                old_vrb = ebdy_old.interpolate_radial_to_boundary_normal_derivative(
                    vo[0])
                old_urrb = ebdy_old.interpolate_radial_to_boundary_normal_derivative2(
                    uo[0])
                old_vrrb = ebdy_old.interpolate_radial_to_boundary_normal_derivative2(
                    vo[0])
                # i think the old parm is right, but should think about
                old_ub_interp = interp(old_ub)
                old_vb_interp = interp(old_vb)
                old_urb_interp = interp(old_urb)
                old_vrb_interp = interp(old_vrb)
                old_urrb_interp = interp(old_urrb)
                old_vrrb_interp = interp(old_vrrb)
                old_ubs_interp = interp(d1_der(old_ub))
                old_vbs_interp = interp(d1_der(old_vb))
                old_urbs_interp = interp(d1_der(old_urb))
                old_vrbs_interp = interp(d1_der(old_vrb))
                old_urrbs_interp = interp(d1_der(old_urrb))
                old_vrrbs_interp = interp(d1_der(old_vrrb))

                xx = aap.x[fc3l]
                yy = aap.y[fc3l]

                def objective(s, r, so, ro):
                    f = np.empty([s.size, 4])
                    f[:, 0] = old_bx_interp(so) + ro * old_nx_interp(
                        so) + 2 * dt * ub_interp(s) + 2 * dt * r * urb_interp(
                            s) + dt * r**2 * urrb_interp(s) - xx
                    f[:, 1] = old_by_interp(so) + ro * old_ny_interp(
                        so) + 2 * dt * vb_interp(s) + 2 * dt * r * vrb_interp(
                            s) + dt * r**2 * vrrb_interp(s) - yy
                    f[:, 2] = bx_interp(s) + r * nx_interp(
                        s
                    ) + 1.5 * dt * ub_interp(s) + 1.5 * dt * r * urb_interp(
                        s) + 0.75 * dt * r**2 * urrb_interp(
                            s) - 0.5 * dt * old_ub_interp(
                                so) - 0.5 * dt * ro * old_urb_interp(
                                    so) - 0.25 * dt * ro**2 * old_urrb_interp(
                                        so) - xx
                    f[:, 3] = by_interp(s) + r * ny_interp(
                        s
                    ) + 1.5 * dt * vb_interp(s) + 1.5 * dt * r * vrb_interp(
                        s) + 0.75 * dt * r**2 * vrrb_interp(
                            s) - 0.5 * dt * old_vb_interp(
                                so) - 0.5 * dt * ro * old_vrb_interp(
                                    so) - 0.25 * dt * ro**2 * old_vrrb_interp(
                                        so) - yy
                    return f

                def Jac(s, r, so, ro):
                    J = np.empty([s.size, 4, 4])
                    # derivative with respect to s
                    J[:, 0,
                      0] = 2 * dt * ubs_interp(s) + 2 * dt * r * urbs_interp(
                          s) + dt * r**2 * urrbs_interp(s)
                    J[:, 1,
                      0] = 2 * dt * vbs_interp(s) + 2 * dt * r * vrbs_interp(
                          s) + dt * r**2 * vrrbs_interp(s)
                    J[:, 2, 0] = bxs_interp(
                        s) + r * nxs_interp(s) + 1.5 * dt * ubs_interp(
                            s) + 1.5 * dt * r * urbs_interp(
                                s) + 0.75 * dt * r**2 * urrbs_interp(s)
                    J[:, 3, 0] = bys_interp(
                        s) + r * nys_interp(s) + 1.5 * dt * vbs_interp(
                            s) + 1.5 * dt * r * vrbs_interp(
                                s) + 0.75 * dt * r**2 * vrrbs_interp(s)
                    # derivative with respect to r
                    J[:, 0,
                      1] = 2 * dt * urb_interp(s) + 2 * dt * r * urrb_interp(s)
                    J[:, 1,
                      1] = 2 * dt * vrb_interp(s) + 2 * dt * r * vrrb_interp(s)
                    J[:, 2, 1] = nx_interp(s) + 1.5 * dt * urb_interp(
                        s) + 1.5 * dt * r * urrb_interp(s)
                    J[:, 3, 1] = ny_interp(s) + 1.5 * dt * vrb_interp(
                        s) + 1.5 * dt * r * vrrb_interp(s)
                    # derivative with respect to so
                    J[:, 0, 2] = old_bxs_interp(so) + ro * old_nxs_interp(so)
                    J[:, 1, 2] = old_bys_interp(so) + ro * old_nys_interp(so)
                    J[:, 2, 2] = -0.5 * dt * old_ubs_interp(
                        so) - 0.5 * dt * ro * old_urbs_interp(
                            so) - 0.25 * dt * ro**2 * old_urrbs_interp(so)
                    J[:, 3, 2] = -0.5 * dt * old_vbs_interp(
                        so) - 0.5 * dt * ro * old_vrbs_interp(
                            so) - 0.25 * dt * ro**2 * old_vrrbs_interp(so)
                    # derivative with respect to ro
                    J[:, 0, 3] = old_nx_interp(so)
                    J[:, 1, 3] = old_ny_interp(so)
                    J[:, 2, 3] = -0.5 * dt * old_urb_interp(
                        so) - 0.5 * dt * ro * old_urrb_interp(so)
                    J[:, 3, 3] = -0.5 * dt * old_vrb_interp(
                        so) - 0.5 * dt * ro * old_vrrb_interp(so)
                    return J

                # take as guess inds our s, r
                s = AEP.full_t[fc3l]
                r = AEP.full_r[fc3l]
                so = OAEP.full_t[fc3l]
                ro = OAEP.full_r[fc3l]
                # now solve for sd, rd
                res = objective(s, r, so, ro)
                mres1 = np.hypot(res[:, 0], res[:, 1]).max()
                mres2 = np.hypot(res[:, 2], res[:, 3]).max()
                mres = max(mres1, mres2)
                tol = 1e-12
                while mres > tol:
                    J = Jac(s, r, so, ro)
                    d = np.linalg.solve(J, res)
                    s -= d[:, 0]
                    r -= d[:, 1]
                    so -= d[:, 2]
                    ro -= d[:, 3]
                    res = objective(s, r, so, ro)
                    mres1 = np.hypot(res[:, 0], res[:, 1]).max()
                    mres2 = np.hypot(res[:, 2], res[:, 3]).max()
                    mres = max(mres1, mres2)
                r_fail_1 = r.max() > 0.0
                r_fail_2 = r.min() < -ebdy.radial_width
                ro_fail_1 = ro.max() > 0.0
                ro_fail_2 = ro.min() < -ebdy_old.radial_width
                r_fail = r_fail_1 or r_fail_2
                ro_fail = ro_fail_1 or ro_fail_2
                fail = r_fail or ro_fail
                fail_amount = 0.0
                if fail:
                    if r_fail_1:
                        fail_amount = max(fail_amount, r.max())
                        r[r > 0.0] = 0.0
                    if r_fail_2:
                        fail_amount = max(fail_amount,
                                          (-r - ebdy.radial_width).max())
                        r[r < -ebdy.radial_width] = -ebdy.radial_width
                    if ro_fail_1:
                        fail_amount = max(fail_amount, ro.max())
                        ro[ro > 0.0] = 0.0
                    if ro_fail_2:
                        fail_amount = max(fail_amount,
                                          (-ro - ebdy_old.radial_width).max())
                        ro[ro <
                           -ebdy_old.radial_width] = -ebdy_old.radial_width

                # get the departure points
                xd = bx_interp(s) + nx_interp(s) * r
                yd = by_interp(s) + ny_interp(s) * r
                xD = old_bx_interp(so) + old_nx_interp(so) * ro
                yD = old_by_interp(so) + old_ny_interp(so) * ro
                xd_all[fc3l] = xd
                yd_all[fc3l] = yd
                xD_all[fc3l] = xD
                yD_all[fc3l] = yD

        self.new_ebdyc = new_ebdyc
        self.xd_all = xd_all
        self.yd_all = yd_all
        self.xD_all = xD_all
        self.yD_all = yD_all

        return self.new_ebdyc
예제 #6
0
파일: fe_advector.py 프로젝트: dbstein/ipde
    def generate(self, dt, fixed_grid=False):
        """
        If fixed_grid = True, reuse same grid
        Otherwise, generate new grid
        """
        ebdyc = self.ebdyc
        u, v = self.u, self.v
        ux, uy, vx, vy = self.ux, self.uy, self.vx, self.vy
        # interpolate the velocity
        ubs = ebdyc.interpolate_radial_to_boundary(u)
        vbs = ebdyc.interpolate_radial_to_boundary(v)

        # move all boundarys; generate new embedded boundaries
        new_ebdys = []
        self.reparmed_ubs = []
        self.reparmed_vbs = []
        for ind, ebdy in enumerate(ebdyc):
            # interpolate the velocity
            ub = ubs[ind]
            vb = vbs[ind]
            # move the boundary with Forward Euler
            bx = ebdy.bdy.x + dt*ub
            by = ebdy.bdy.y + dt*vb
            # repararmetrize the boundary
            bx, by, new_t = arc_length_parameterize(bx, by, filter_fraction=self.filter_fraction, return_t=True)
            # bx, by, new_t = bx, by, np.linspace(0, 2*np.pi, bx.size, endpoint=False)
            # bx, by, new_t = arc_length_parameterize(bx, by, return_t=True, filter_function=self.filter_function)
            # move these boundary values to the new parametrization
            # This is not necessary for this timestepper, but is used by other
            # timesteppers which use this as a startup!
            # SHOULD I SWITCH THIS TO NUFFT WHEN THAT IS BEING USED?
            self.reparmed_ubs.append(nufft_interpolation1d(new_t, np.fft.fft(ub)))
            self.reparmed_vbs.append(nufft_interpolation1d(new_t, np.fft.fft(vb)))
            # bu_interp = interp1d(0, 2*np.pi, ebdy.bdy.dt, ub, p=True)
            # bv_interp = interp1d(0, 2*np.pi, ebdy.bdy.dt, vb, p=True)
            # self.reparmed_ubs.append(bu_interp(new_t))
            # self.reparmed_vbs.append(bv_interp(new_t))
            # generate the new embedded boundary
            new_ebdy = ebdy.regenerate(bx, by)
            new_ebdys.append(new_ebdy)
        new_ebdyc = EmbeddedBoundaryCollection(new_ebdys)
        # get dnager zone distance
        umax = np.sqrt(u*u + v*v).max()
        ddd = 2*umax*dt
        # raise an exception if danger zone thicker than radial width
        if ddd > new_ebdyc[0].radial_width:
            raise Exception('Velocity is so fast that one timestep oversteps safety zones; reduce timestep.')
        # register the grid...
        if fixed_grid:
            new_ebdyc.register_grid(ebdyc.grid, danger_zone_distance=ddd)
        else:
            new_ebdyc.generate_grid(danger_zone_distance=ddd)

        # let's get the points that need to be interpolated to
        aap = new_ebdyc.pnar
        AP_key  = ebdyc.register_points(aap.x, aap.y, dzl=new_ebdyc.danger_zone_list, gil=new_ebdyc.guess_ind_list)

        # now we need to interpolate onto things
        AEP = ebdyc.registered_partitions[AP_key]

        # get departure points
        xd_all = np.zeros(aap.N)
        yd_all = np.zeros(aap.N)

        c1n, c2n, c3n = AEP.get_Ns()
        # category 1 and 2
        c1_2n = c1n + c2n
        c1_2 = AEP.zone1_or_2
        uxh = ebdyc.interpolate_to_points(ux, aap.x, aap.y)
        uyh = ebdyc.interpolate_to_points(uy, aap.x, aap.y)
        vxh = ebdyc.interpolate_to_points(vx, aap.x, aap.y)
        vyh = ebdyc.interpolate_to_points(vy, aap.x, aap.y)
        uh = ebdyc.interpolate_to_points(u, aap.x, aap.y)
        vh = ebdyc.interpolate_to_points(v, aap.x, aap.y)
        SLM = np.zeros([c1_2n,] + [2,2], dtype=float)
        SLR = np.zeros([c1_2n,] + [2,], dtype=float)
        SLM[:,0,0] = 1 + dt*uxh[c1_2]
        SLM[:,0,1] = dt*uyh[c1_2]
        SLM[:,1,0] = dt*vxh[c1_2]
        SLM[:,1,1] = 1 + dt*vyh[c1_2]
        SLR[:,0] = dt*uh[c1_2]
        SLR[:,1] = dt*vh[c1_2]
        OUT = np.linalg.solve(SLM, SLR)
        xdt, ydt = OUT[:,0], OUT[:,1]
        xd, yd = aap.x[c1_2] - xdt, aap.y[c1_2] - ydt
        xd_all[c1_2] = xd
        yd_all[c1_2] = yd
        # categroy 3... this is the tricky one
        if c3n > 0:
            for ind, ebdy in enumerate(ebdyc):
                ub = ubs[ind]
                vb = vbs[ind]
                
                c3l = AEP.zone3l[ind]
                th = ebdy.bdy.dt
                # th = 2*np.pi/nb
                # tk = np.fft.fftfreq(nb, th/(2*np.pi))
                tk = ebdy.bdy.k
                def d1_der(f):
                    return np.fft.ifft(np.fft.fft(f)*tk*1j).real
                interp = lambda f: interp1d(0, 2*np.pi, th, f, k=3, p=True)
                bx_interp  = interp(ebdy.bdy.x)
                by_interp  = interp(ebdy.bdy.y)
                bxs_interp = interp(d1_der(ebdy.bdy.x))
                bys_interp = interp(d1_der(ebdy.bdy.y))
                nx_interp  = interp(ebdy.bdy.normal_x)
                ny_interp  = interp(ebdy.bdy.normal_y)
                nxs_interp = interp(d1_der(ebdy.bdy.normal_x))
                nys_interp = interp(d1_der(ebdy.bdy.normal_y))
                urb = ebdy.interpolate_radial_to_boundary_normal_derivative(u[ind])
                vrb = ebdy.interpolate_radial_to_boundary_normal_derivative(v[ind])
                ub_interp   = interp(ub)
                vb_interp   = interp(vb)
                urb_interp  = interp(urb)
                vrb_interp  = interp(vrb)
                ubs_interp  = interp(d1_der(ub))
                vbs_interp  = interp(d1_der(vb))
                urbs_interp = interp(d1_der(urb))
                vrbs_interp = interp(d1_der(vrb))
                xo = aap.x[c3l]
                yo = aap.y[c3l]
                def objective(s, r):
                    f = np.empty([s.size, 2])
                    f[:,0] = bx_interp(s) + r*nx_interp(s) + dt*ub_interp(s) + dt*r*urb_interp(s) - xo
                    f[:,1] = by_interp(s) + r*ny_interp(s) + dt*vb_interp(s) + dt*r*vrb_interp(s) - yo
                    return f
                def Jac(s, r):
                    J = np.empty([s.size, 2, 2])
                    J[:,0,0] = bxs_interp(s) + r*nxs_interp(s) + dt*ubs_interp(s) + dt*r*urbs_interp(s)
                    J[:,1,0] = bys_interp(s) + r*nys_interp(s) + dt*vbs_interp(s) + dt*r*vrbs_interp(s)
                    J[:,0,1] = nx_interp(s) + dt*urb_interp(s)
                    J[:,1,1] = ny_interp(s) + dt*vrb_interp(s)
                    return J
                # take as guess inds our s, r
                s = AEP.zone3t[ind]
                r = AEP.zone3r[ind]
                # now solve for sd, rd
                res = objective(s, r)
                mres = np.hypot(res[:,0], res[:,1]).max()
                tol = 1e-12
                while mres > tol:
                    J = Jac(s, r)
                    d = np.linalg.solve(J, res)
                    s -= d[:,0]
                    r -= d[:,1]
                    res = objective(s, r)
                    mres = np.hypot(res[:,0], res[:,1]).max()
                # get the departure points
                xd = bx_interp(s) + nx_interp(s)*r
                yd = by_interp(s) + ny_interp(s)*r
                xd_all[c3l] = xd
                yd_all[c3l] = yd

        self.new_ebdyc = new_ebdyc
        self.xd_all = xd_all
        self.yd_all = yd_all

        return self.new_ebdyc