def centralBump(self, t0, grid): from mpi4py import MPI rank = MPI.COMM_WORLD.rank r, phi = grid.axes[0], grid.axes[1] r3ind = int(r.shape[0] / 6) r3val = r[r3ind] r6val = r[6 * r3ind] phi3ind = int(phi.shape[0] / 5) phi3val = phi[phi3ind] phi6val = phi[4 * phi3ind] rmid = int(r.shape[0] / 2) phimid = int(phi.shape[0] / 2) r_mesh, phi_mesh = grid.meshes def exp_bump(p): rv = np.exp(-20*(p[0]-r[rmid])**2)*\ np.exp(-5*(p[1]-phi[phimid])**2) return rv def bump(p): v = max(0.0,(-p[0] + r3val) * (p[0] - r6val))*\ max(0.0,(-p[1] + phi3val) * (p[1] - phi6val)) return float(v)**4 #rv = np.apply_along_axis(bump,2,grid) rv = np.exp(-20*(r_mesh - r[rmid])**2)*\ np.exp(-5*(phi_mesh - phi[phimid])**2) #rv = np.apply_along_axis(exp_bump,2,grid) #rv = rv/np.amax(rv) if rank == 0: rtslice = tslices.TimeSlice([rv], grid, t0) else: rtslice = tslices.TimeSlice([np.zeros_like(rv)], grid, t0) return rtslice
def _NR(self, u_start, u_next, t, dt, domain): """A Newton-Raphson auxilliary routine for the implementation of the implicit Euler scheme. Parameters ---------- u_start: numpy.ndarray Initial values of the function. u_next: numpy.ndarray The first guess at the next values of the function. t: float Current time. dt: float Current time step. domain: grid The domain that the function is being evaluated over. """ # Starting guess for Newton-Raphson algorithm. Currently # chooses current tslice. # To be perhaps moved so user specifies this in system file or # perhaps in setup file when choosing implicit Euler. prev_u_next = u_next while (True): # Evolution equation of u g = self.system.evaluate( t + dt, tslices.TimeSlice(prev_u_next, domain, time=t)).data # Derivative of evolution equation of u w.r.t. evolved variable dg, TOL = self.system.implicit_method_jacobian( t + dt, tslices.TimeSlice(prev_u_next, domain, time=t)) dg = dg.data # NR is applied to f f = prev_u_next - u_start - dt * g df = 1. - dt * dg # Compute next value of u_next next_u_next = prev_u_next - f / df # If we get to within a certain accuracy of the root stop if (all(abs(next_u_next - prev_u_next)[0] < TOL)): break # Otherwise continue prev_u_next = next_u_next return next_u_next
def evaluate(self, t, Psi): f0, Dtf0 = Psi.data DxDxf = np.real(self.D(f0, Psi.domain.step_sizes[0])) DtDtf = DxDxf DtDtf[-1] = 0.0 DtDtf[0] = 0.0 return tslices.TimeSlice([Dtf0, DtDtf], Psi.domain, time=t)
def implicit_method_jacobian(self, t, Psi): D_Dtf = np.zeros_like(Psi.data[0]) rtslice = tslices.TimeSlice([D_Dtf], Psi.domain, time=t) if __debug__: self.log.debug("Exiting Jacobian calculation with timeslice = %s" % repr(rtslice)) return rtslice, self.implicit_int_tol
def centralBump(self, t0, grid): self.log.info("Initial value routine = central bump") r = grid.axes[0] length = grid.bounds[0][1] - grid.bounds[0][0] rv = np.maximum(0.0, (36) * (1 / length)**2 * (-r + length / 3) * (r - 2 * length / 3))**8 if __debug__: self.log.debug(repr(rv)) #if np.amax(rv is not 0: #rv = 0.5*rv/np.amax(rv) rtslice = tslices.TimeSlice(np.array([rv]), grid, t0) return rtslice
def evaluate(self, t, Psi, intStep = None): if __debug__: self.log.debug("Entered evaluation: t = %f, Psi = %s, intStep = %s"%\ (t,Psi,intStep)) # Define useful variables f0, Dtf0 = Psi.data x = Psi.domain dx = Psi.domain.step_sizes[0] tau = self.tau ######################################################################## # Calculate derivatives ######################################################################## if __debug__: self.log.debug("f0.shape = %s"%repr(f0.shape)) DxDxf = np.real(self.D(f0,dx)) DtDtf = DxDxf if __debug__: self.log.debug("""Derivatives are: DtDtf = %s"""%\ (repr(DtDtf))) ######################################################################## # Impose boundary conditions ######################################################################## DtDtf[-1] = 0 #DtDtf[0] #self.boundaryRight(t,Psi) DtDtf[0] = 0 #self.boundaryLeft(t,Psi) #DtDtf = DtDtf + \ # tau*(f0[0] - self.boundaryLeft(t,Psi))*\ # self.D.penalty_boundary(1,dx[0],DtDtf.shape) + \ # tau*(f0[-1] - self.boundaryRight(t,Psi))*\ # self.D.penalty_boundary(-1,dx[0],DtDtf.shape) # now all time derivatives are computed # package them into a time slice and return rtslice = tslices.TimeSlice([Dtf0,DtDtf],Psi.domain,time=t) if __debug__: self.log.debug("Exiting evaluation with TimeSlice = %s"%repr(rtslice)) return rtslice
def centralBump(self,t0,grid): r = grid.axes r3ind = int(r.shape[0]/6) r3val = r[r3ind] r6val = r[6*r3ind] def bump(p): v = float(max(0.0,(-p + r3val) * (p - r6val)))**4 return v def deriv_bump(p): #if r3ind < p < r6ind: # return float(-2*p+r6val+r3val) return float(0) rv = np.vectorize(bump)(grid) ru = np.vectorize(deriv_bump)(grid) rv = 0.5*rv/np.amax(rv) ru = 0.5*ru/np.amax(rv) rtslice = tslices.TimeSlice([rv,ru],grid,t0) return rtslice
def evaluate(self, t, Psi, intStep=None): self.log.debug("Entered evaluation: t = %f, Psi = %s, intStep = %s"%\ (t,Psi,intStep)) # Define useful variables f0 = Psi.data[0] x = Psi.domain.axes[0] dx = Psi.domain.step_sizes[0] tau = self.tau ######################################################################## # Calculate derivatives ######################################################################## Dxf = np.real(self.D(f0, dx)) Dtf = Dxf penalty_term = self.D.penalty_boundary(dx, 1) Dtf[-penalty_term.shape[0]:] -= tau * (f0[-1] - self.boundaryRight(t,Psi)) \ * penalty_term if __debug__: self.log.debug("""Derivatives are: Dtf = %s"""%\ (repr(Dtf))) ######################################################################## # Impose boundary conditions ######################################################################## #Dtf[-1]= 0. #self.boundaryRight(t,Psi) #Dtf[0]= self.boundaryLeft(t,Psi) #Dtf[-1] = Dtf[0] #now all time derivatives are computed #package them into a time slice and return rtslice = tslices.TimeSlice([Dtf], Psi.domain, time=t) if __debug__: self.log.debug("Exiting evaluation with timeslice = %s" % repr(rtslice)) return rtslice
def evaluate(self, t, Psi, intStep=None): if __debug__: self.log.debug("Entered evaluation: t = %f, Psi = %s, intStep = %s"%\ (t,Psi,intStep)) # Define useful variables f0 = Psi.data[0] x = Psi.domain.axes[0] dx = Psi.domain.step_sizes[0] tau = self.tau ######################################################################## # Calculate derivatives ######################################################################## Dxf = np.real(self.D(f0, dx)) Dtf = self.speed * Dxf gp_processor = partial(ghost_point_processor, log=self.log) new_derivative, _ = Psi.communicate(gp_processor, data=np.array([Dtf])) Dtf = new_derivative[0] if __debug__: self.log.debug("""Derivatives are: Dtf = %s""" % (repr(Dtf))) ######################################################################## # Impose boundary conditions ######################################################################## #Dtf[-1]= 0.#self.boundaryRight(t,Psi) if Psi.domain.mpi.comm.rank == 0: Dtf[0] = self.boundaryLeft(t, Psi) #Dtf[-1] = Dtf[0] # now all time derivatives are computed # package them into a time slice and return rtslice = tslices.TimeSlice(np.array([Dtf]), Psi.domain, time=t) if __debug__: self.log.debug("Exiting evaluation with timeslice = %s" % repr(rtslice)) return rtslice
def advance(self, t, u, dt): """An implicit Euler method implementation of ABCSolver. See the ABCSolver.advance method for documentation. """ # Current values of the evolved variables u_start = u.data # Initial guess for the Newton-Raphson method is the current value(s) # of the evolved variables u_next = u_start # prev_u_next = u_next prev_u_next = u_next # Returns u_next from applying Newton-Raphson u_ret = self._NR(u_start, u_next, t, dt, u.domain) r_time = t + dt r_slice = tslices.TimeSlice(u_ret, u.domain, r_time) return (r_time, r_slice)
def evaluate(self, t, tslice, intStep=None): if __debug__: self.log.debug("Entered evaluation: t = %f, tslice = %s, intStep = %s"%\ (t, tslice, intStep)) # Define useful variables f = tslice.data[0] ######################################################################## # Calculate derivatives ######################################################################## ethf = self.eth(f, [0], self.lmax) dtf = self.ethp(ethf[0], [1], self.lmax) if __debug__: self.log.debug("""Derivatives are: dtf = %s """ % (repr(dtf))) ######################################################################## # Impose boundary conditions ######################################################################## # pt = self.D.penalty_boundary(dr, "right") # pt_shape = pt.size # # dtphi0[-pt_shape:] -= tau * (phi0[-1] - self.SATphi0(t, tslice)) * pt # dtphi2[:pt_shape] -= tau * (phi2[0] - self.SATphi2(t, tslice)) * pt ######################################################################## # Packaging ######################################################################## rtslice = tslices.TimeSlice(dtf, tslice.domain, time=t) if __debug__: self.log.debug("Exiting evaluation with timeslice = %s" % repr(rtslice)) return rtslice
def data(self, t0, grid): rv = np.array([ 0.00000401632684942, 0.00000192499658763, 0.00000099772870147,\ 0.00000022765183832, 0.00000046507080863, -0.0000003300452312 ,\ 0.00000062974172828, -0.00000084085150719, 0.00000122978111633,\ -0.00000173153916076, 0.00000243852897086, -0.00000339401167924,\ 0.00000468353699582, -0.00000640006545601, 0.00000866039005127,\ -0.00001159615978749, 0.00001534736518352, -0.00002004222246138,\ 0.00002576538282592, -0.00003251084480869, 0.0000401219186533 ,\ -0.00004822399684474, 0.00005616161979072, -0.00006295603141441,\ 0.00006730239613382, -0.00006762518639408, 0.00006220491467334,\ -0.0000493790556335 , 0.00002780564387487, 0.00000323813794329,\ -0.00004356481100534, 0.00009184500062725, -0.00014548888853252,\ 0.00020068538741031, -0.00025262465531646, 0.00029590251389135,\ -0.00032507451254041, 0.00033529828730872, -0.00032298121854387,\ 0.00028634089954959, -0.00022579126761677, 0.00014408737801006,\ -0.00004619390760402, -0.00006111857691737, 0.00016990621035476,\ -0.00027183673081992, 0.00035902855096032, -0.00042483915235696,\ 0.00046450680546802, -0.00047557203841141, 0.00045803716953868,\ -0.00041425815985836, 0.00034859741282364, -0.00026689395793278,\ 0.00017582532588945, -0.00008224165993041, -0.00000745225032476,\ 0.00008780553643091, -0.00015467906027939, 0.00020543401573565,\ -0.00023895456368999, 0.0002555262007749 , -0.00025660403132089,\ 0.0002445120127969 , -0.00022211440620396, 0.00019249677896301,\ -0.00015868547023992, 0.00012342541952096, -0.00008902553443739,\ 0.0000572726977001 , -0.00002940740612892, 0.00000615033664036,\ 0.00001223462391232, -0.00002585437390634, 0.00003509147037659,\ -0.00004050974746794, 0.00004276960709606, -0.00004255693092361,\ 0.0000405291526316 , -0.00003727739758106, 0.0000333046546635 ,\ -0.00002901606283444, 0.00002472000591966, -0.00002063537528648,\ 0.0000169039610633 , -0.00001360432584562, 0.00001076564712092,\ -0.00000838344097786, 0.00000642403682553, -0.00000485353496625,\ 0.00000359675704848, -0.00000265847140611, 0.00000186187684214,\ -0.00000143563257268, 0.00000077349425006, -0.00000096984553866,\ -0.00000014450388622, -0.00000125698079451, -0.00000141060384138,\ -0.00000214380180203, -0.0000024309521466 ]) return tslices.TimeSlice(np.array([rv]), grid, t0)
def initial_data(self, t, grid): if __debug__: self.log.info("Initial value routine = %s" % self.iv_routine) values = getattr(self, self.iv_routine, None)(t, grid) return tslices.TimeSlice([values], grid, t)
def sin(self,t0,grid): r = grid.axes print r rv = np.sin(2*math.pi*r/(grid[-1]-grid[0])) rtslice = tslices.TimeSlice([rv,np.zeros_like(rv)],grid,t0) return rtslice
def exp_bump(self, t0, grid): axis = grid.axes[0] mid_ind = int(axis.shape[0] / 2) rv = 0.5 * np.exp(-40 * (axis - axis[mid_ind]) * (axis - axis[mid_ind])) return tslices.TimeSlice([rv], grid, t0)
def sin(self, t0, grid): r = grid.axes rv = np.sin(2 * math.pi * r / (grid[-1] - grid[0])) rtslice = tslices.TimeSlice([0.5 * rv], grid, t0) return rtslice
def exp_bump(self, t, grid): axes = grid.axes[0] mid_ind = int(axes.shape[0] / 2) rv = (1 / 72.0) * length**2 * np.exp(-40 * (axes - axes[mid_ind]) * (axes - axes[mid_ind])) return tslices.TimeSlice(np.array([rv]), grid, t)
def evaluate(self, t, Psi, intStep=None): #if __debug__: # self.log.debug("Entered evaluation: t = %f, Psi = %s, intStep = %s"%\ # (t,Psi,intStep)) # Define useful variables f0, = Psi.data x = Psi.domain.axes[0] y = Psi.domain.axes[1] dx = Psi.domain.step_sizes[0] dy = Psi.domain.step_sizes[1] tau = self.tau ######################################################################## # Calculate derivatives and impose boundary conditions ######################################################################## Dxf = np.apply_along_axis(lambda x: self.Dx(x, dx), 0, f0) #if __debug__: # self.log.debug("Dxf is %s"%repr(Dxf)) Dyf = np.apply_along_axis(lambda y: self.Dy(y, dy), 1, f0) if __debug__: self.log.debug("""Derivatives are: Dxf = %s""" % (repr(Dxf))) self.log.debug("""Derivatives are: Dyf = %s""" % (repr(Dyf))) ######################################################################## # Impose boundary conditions ######################################################################## # implementation follows Carpenter et al. # using the SAT method # at the boundaries we need boundary conditions # implemented as penalty terms the objects in diffop.py know how to # do this. # # tau is the penalty parameter and will need to take on different # values depending on the operator. # pt_x_r = self.Dx.penalty_boundary(dx, "right") pt_x_r_shape = pt_x_r.size pt_x_l = self.Dx.penalty_boundary(dx, "left") pt_x_l_shape = pt_x_l.size pt_y_r = self.Dy.penalty_boundary(dy, "right") pt_y_r_shape = pt_y_r.size pt_y_l = self.Dy.penalty_boundary(dy, "left") pt_y_l_shape = pt_y_l.size #First do internal boundaries if __debug__: self.log.debug("Implementing internal boundaries") _, b_values = Psi.communicate() # compare to OneDAdvection for an # alternative way to handle this. if __debug__: self.log.debug("b_values = %s" % repr(b_values)) for d_slice, data in b_values: if __debug__: self.log.debug("d_slice is %s" % (repr(d_slice))) self.log.debug("recieved_data is %s" % (data)) #the calculation of sigma constants is taken from Carpenter, #Nordstorm and Gottlieb. Note that in this paper the metric H is #always set to the identity matrix. Beware: in some presentations #of SBP operators it is not the identitiy. This is accounted for #in the calculation of pt below. #I think that this paper implicitly assumes that 'a' is positive #hence the difference for psi4 from the calculations given in #the paper. This change accounts for the negative eigenvalue #associated to psi4. #Note that sigma3 = sigma1 - eigenvalue_on_boundary, at least when #the eigenvalue is positive. For negative eigenvalue it seems to me #that the roles of sigma3 and sigma1 are reversed. x_chara = self.xcoef y_chara = self.ycoef if x_chara > 0: sigma3x = 0.25 sigma1x = sigma3x - 1 else: sigma1x = 0.25 sigma3x = sigma1x - 1 if y_chara > 0: sigma3y = 0.25 sigma1y = sigma3y - 1 else: sigma1y = 0.25 sigma3y = sigma1y - 1 if d_slice[1] == slice(-1, None, None): if __debug__: self.log.debug("Calculating right x boundary") Dxf[-pt_x_r_shape:] += sigma1x * x_chara * pt_x_r * ( f0[d_slice[1:]] - data[0]) elif d_slice[1] == slice(None, 1, None): if __debug__: self.log.debug("Calculating left x boundary") Dxf[:pt_x_l_shape] += sigma3x * x_chara * pt_x_l * ( f0[d_slice[1:]] - data[0]) elif d_slice[1] == slice(None, None, None): if d_slice[2] == slice(-1, None, None): if __debug__: self.log.debug("Calculating right y boundary") Dyf[:, -pt_y_r_shape:] += sigma1y * y_chara * pt_y_r * ( f0[d_slice[1:]] - data[0]) elif d_slice[2] == slice(None, 1, None): if __debug__: self.log.debug("Calculating left y boundary") Dyf[:, :pt_y_l_shape] += sigma3y * y_chara * pt_y_l * ( f0[d_slice[1:]] - data[0]) #Now do the external boundaries if __debug__: self.log.debug("Implementing external boundary") b_data = Psi.external_slices() if __debug__: self.log.debug("b_data = %s" % repr(b_data)) for dim, direction, d_slice in b_data: if __debug__: self.log.debug("Boundary slice is %s" % repr(d_slice)) self.log.debug("Dimension is %d" % dim) self.log.debug("Direction is %d" % direction) d_slice = d_slice[1:] if dim == 0: if self.xcoef > 0 and direction == 1: if __debug__: self.log.debug("Doing right hand x boundary") Dxf[-pt_x_r_shape:] -= tau * self.xcoef * \ (f0[d_slice] - self.boundary(t,Psi)[d_slice]) * pt_x_r if self.xcoef < 0 and direction == -1: if __debug__: self.log.debug("Doing left hand x boundary") Dxf[:pt_x_l_shape] += tau * self.xcoef * \ (f0[d_slice] - self.boundary(t,Psi)[d_slice]) * pt_x_l elif dim == 1: if self.ycoef > 0 and direction == 1: if __debug__: self.log.debug("Doing right hand y boundary") Dyf[:,-pt_y_r_shape:] -= tau * self.ycoef * \ (f0[d_slice] - self.boundary(t,Psi)[d_slice]) * pt_y_r if self.ycoef < 0 and direction == -1: if __debug__: self.log.debug("Doing left hand y boundary") Dyf[:,:pt_y_l_shape] += tau * self.ycoef * \ (f0[d_slice] - self.boundary(t,Psi)[d_slice]) * pt_y_l Dtf = self.xcoef * Dxf + self.ycoef * Dyf # now all time derivatives are computed # package them into a time slice and return rtslice = tslices.TimeSlice([Dtf], Psi.domain, time=t) if __debug__: self.log.debug("Exiting evaluation with TimeSlice = %s" % repr(rtslice)) return rtslice
def evaluate(self, t, Psi, intStep = None): if __debug__: self.log.debug("Entered evaluation: t = %f, Psi = %s, intStep = %s"%\ (t,Psi,intStep)) # Define useful variables f0 = Psi.data[0] x = Psi.domain.axes[0] dx = Psi.domain.step_sizes[0] tau = self.tau ######################################################################## # Calculate derivatives ######################################################################## Dxf = np.real(self.D(f0,dx)) Dtf = self.speed * Dxf if __debug__: self.log.debug("Derivatives without boundary implementation is Dtf = %s"%repr(Dtf)) #First do internal boundaries pt_r = self.D.penalty_boundary(dx, "right") pt_l = self.D.penalty_boundary(dx, "left") if self.D.boundary_type == sbp.BOUNDARY_TYPE_GHOST_POINTS: gp_processor = partial( ghost_point_processor, log=self.log ) if __debug__: self.log.debug("Implementing internal boundary using ghost points") new_derivative, _ = Psi.communicate( gp_processor, data=np.array([Dtf]) ) elif self.D.boundary_type == sbp.BOUNDARY_TYPE_SAT: gp_processor = partial( sbp_ghost_point_processor, speed=self.speed, f0=f0, Dtf=Dtf, pt_r=pt_r, pt_l=pt_l, log=self.log ) if __debug__: self.log.debug("Implementing internal boundary using sat") new_derivative, _ = Psi.communicate(gp_processor) else: raise Exception("Unknown boundary type encountered") Dtf = new_derivative[0] #Now do the external boundaries if __debug__: self.log.debug("Implementing external boundary") b_data = Psi.external_slices() if __debug__: self.log.debug("b_data = %s"%repr(b_data)) for dim, direction, d_slice in b_data: if __debug__: self.log.debug("Boundary slice is %s"%repr(d_slice)) if self.speed > 0 and direction == 1: if __debug__: self.log.debug("Doing external boundary on right") Dtf[-pt_r.size:] -= tau * self.speed * ( f0[-1] - self.boundaryRight(t,Psi) ) * pt_r elif self.speed < 0 and direction == -1: if __debug__: self.log.debug("Doing external boundary on left") Dtf[:pt_l.size] -= tau * self.speed * ( f0[0] - self.boundaryRight(t,Psi) ) * pt_l if __debug__: self.log.debug("""Derivatives are: Dtf = %s"""%\ (repr(Dtf))) # now all time derivatives are computed # package them into a time slice and return rtslice = tslices.TimeSlice(np.array([Dtf]), Psi.domain, time=t) if __debug__: self.log.debug("Exiting evaluation with timeslice = %s"% repr(rtslice)) return rtslice
def initial_data(self, t0, grid): axis = grid.axes[0] rv = 0.5 * np.exp(-10 * (axis - axis[int(axis.shape[0] / 2)])**2) return tslices.TimeSlice([rv, np.zeros_like(rv)], grid, t0)