def assemble_ehpq(self, e=None, h=None, p=None, q=None, discr=None): if discr is None: def zero(): return 0 else: def zero(): return discr.volume_zeros() from grudge.tools import count_subset e_components = count_subset(self.get_eh_subset()[0:3]) h_components = count_subset(self.get_eh_subset()[3:6]) def default_fld(fld, comp): if fld is None: return [zero() for i in range(comp)] else: return fld e = default_fld(e, e_components) h = default_fld(h, h_components) p = default_fld(p, self.dimensions) q = default_fld(q, self.dimensions) from grudge.tools import join_fields return join_fields(e, h, p, q)
def __call__(self, t, x_vec): # JSH/TW Nodal DG Methods, p.326 rho = numpy.ones_like(x_vec[0]) rho_u = x_vec[1] * x_vec[1] rho_v = numpy.zeros_like(x_vec[0]) e = (2 * self.mu * x_vec[0] + 10) / (self.gamma - 1) + x_vec[1]**4 / 2 from grudge.tools import join_fields return join_fields(rho, e, rho_u, rho_v)
def __call__(self, t, x_vec): rho = 2 + numpy.sin(x_vec[0] + x_vec[1] + x_vec[2] - 2 * t) velocity = numpy.array([1, 1, 0]) p = 1 e = p / (self.gamma - 1) + rho / 2 * numpy.dot(velocity, velocity) rho_u = rho * velocity[0] rho_v = rho * velocity[1] rho_w = rho * velocity[2] from grudge.tools import join_fields return join_fields(rho, e, rho_u, rho_v, rho_w)
def sym_operator(self, w=None): from grudge.tools import count_subset fld_cnt = count_subset(self.get_eh_subset()) if w is None: from grudge.symbolic import make_sym_vector w = make_sym_vector("w", fld_cnt + 2 * self.dimensions) from grudge.tools import join_fields return join_fields(MaxwellOperator.sym_operator(self, w[:fld_cnt]), numpy.zeros((2 * self.dimensions, ), dtype=object)) + self.pml_local_op(w)
def __call__(self, t, x_vec, q): vortex_loc = self.center + t * self.velocity # coordinates relative to vortex center x_rel = x_vec[0] - vortex_loc[0] y_rel = x_vec[1] - vortex_loc[1] # sources written in terms of A=1.0 solution # (standard isentropic vortex) from math import pi r = numpy.sqrt(x_rel**2 + y_rel**2) expterm = self.beta * numpy.exp(1 - r**2) u = self.velocity[0] - expterm * y_rel / (2 * pi) v = self.velocity[1] + expterm * x_rel / (2 * pi) rho = (1 - (self.gamma - 1) / (16 * self.gamma * pi**2) * expterm**2)**(1 / (self.gamma - 1)) p = rho**self.gamma #computed necessary derivatives expterm_t = 2 * expterm * x_rel expterm_x = -2 * expterm * x_rel expterm_y = -2 * expterm * y_rel u_x = -expterm * y_rel / (2 * pi) * (-2 * x_rel) v_y = expterm * x_rel / (2 * pi) * (-2 * y_rel) #derivatives for rho (A=1) facG = self.gamma - 1 rho_t = (1/facG)*(1-(facG)/(16*self.gamma*pi**2)*expterm**2)**(1/facG-1)* \ (-facG/(16*self.gamma*pi**2)*2*expterm*expterm_t) rho_x = (1/facG)*(1-(facG)/(16*self.gamma*pi**2)*expterm**2)**(1/facG-1)* \ (-facG/(16*self.gamma*pi**2)*2*expterm*expterm_x) rho_y = (1/facG)*(1-(facG)/(16*self.gamma*pi**2)*expterm**2)**(1/facG-1)* \ (-facG/(16*self.gamma*pi**2)*2*expterm*expterm_y) #derivatives for rho (A=1) to the power of gamma rho_gamma_t = self.gamma * rho**(self.gamma - 1) * rho_t rho_gamma_x = self.gamma * rho**(self.gamma - 1) * rho_x rho_gamma_y = self.gamma * rho**(self.gamma - 1) * rho_y factorA = self.densityA**self.gamma - self.densityA #construct source terms source_rho = x_vec[0] - x_vec[0] source_e = (factorA/(self.gamma-1))*(rho_gamma_t + self.gamma*(u_x*rho**self.gamma+u*rho_gamma_x)+ \ self.gamma*(v_y*rho**self.gamma+v*rho_gamma_y)) source_rhou = factorA * rho_gamma_x source_rhov = factorA * rho_gamma_y from grudge.tools import join_fields return join_fields(source_rho, source_e, source_rhou, source_rhov, x_vec[0] - x_vec[0])
def __call__(self, t, x_vec): ones = numpy.ones_like(x_vec[0]) rho_field = ones*self.rho if self.gaussian_pulse_at is not None: rel_to_pulse = [x_vec[i] - self.gaussian_pulse_at[i] for i in range(len(x_vec))] rho_field += self.pulse_magnitude * self.rho * numpy.exp( - sum(rtp_i**2 for rtp_i in rel_to_pulse)/2) direction = self.direction_vector(x_vec.shape[0]) from grudge.tools import make_obj_array u_field = make_obj_array([ones*self.velocity*dir_i for dir_i in direction]) from grudge.tools import join_fields return join_fields(rho_field, self.e*ones, self.rho*u_field)
def __call__(self, t, x_vec): from grudge.tools import heaviside from grudge.tools import heaviside_a x_rel = x_vec[0] y_rel = x_vec[1] from math import pi r = numpy.sqrt(x_rel**2 + y_rel**2) r_shift = r - 3.0 u = 0.0 v = 0.0 from numpy import sign rho = heaviside(-r_shift) + .125 * heaviside_a(r_shift, 1.0) e = (1.0 / (self.gamma - 1.0)) * (heaviside(-r_shift) + .1 * heaviside_a(r_shift, 1.0)) p = (self.gamma - 1.0) * e from grudge.tools import join_fields return join_fields(rho, e, rho * u, rho * v)
def __call__(self, t, x_vec): vortex_loc = self.center + t*self.velocity # coordinates relative to vortex center x_rel = x_vec[0] - vortex_loc[0] y_rel = x_vec[1] - vortex_loc[1] # Y.C. Zhou, G.W. Wei / Journal of Computational Physics 189 (2003) 159 # also JSH/TW Nodal DG Methods, p. 209 from math import pi r = numpy.sqrt(x_rel**2+y_rel**2) expterm = self.beta*numpy.exp(1-r**2) u = self.velocity[0] - expterm*y_rel/(2*pi) v = self.velocity[1] + expterm*x_rel/(2*pi) rho = (1-(self.gamma-1)/(16*self.gamma*pi**2)*expterm**2)**(1/(self.gamma-1)) p = rho**self.gamma e = p/(self.gamma-1) + rho/2*(u**2+v**2) from grudge.tools import join_fields return join_fields(rho, e, rho*u, rho*v)
def main(write_output=True, flux_type_arg="upwind", dtype=np.float64, debug=[]): from math import sin, cos, pi, exp, sqrt # noqa from grudge.backends import guess_run_context rcon = guess_run_context() if rcon.is_head_rank: from grudge.mesh.reader.gmsh import generate_gmsh mesh = generate_gmsh(GEOMETRY, 2, allow_internal_boundaries=True, force_dimension=2) print("%d elements" % len(mesh.elements)) mesh_data = rcon.distribute_mesh(mesh) else: mesh_data = rcon.receive_mesh() discr = rcon.make_discretization(mesh_data, order=4, debug=debug, default_scalar_type=dtype) from grudge.timestep.runge_kutta import LSRK4TimeStepper stepper = LSRK4TimeStepper(dtype=dtype) from grudge.visualization import VtkVisualizer if write_output: vis = VtkVisualizer(discr, rcon, "fld") source_center = 0 source_width = 0.05 source_omega = 3 import grudge.symbolic as sym sym_x = sym.nodes(2) sym_source_center_dist = sym_x - source_center from grudge.models.wave import StrongWaveOperator op = StrongWaveOperator( -1, discr.dimensions, source_f=sym.FunctionSymbol("sin")( source_omega * sym.ScalarParameter("t")) * sym.FunctionSymbol("exp")( -np.dot(sym_source_center_dist, sym_source_center_dist) / source_width**2), dirichlet_tag="boundary", neumann_tag=BTAG_NONE, radiation_tag=BTAG_NONE, flux_type=flux_type_arg) from grudge.tools import join_fields fields = join_fields( discr.volume_zeros(dtype=dtype), [discr.volume_zeros(dtype=dtype) for i in range(discr.dimensions)]) # diagnostics setup ------------------------------------------------------- from logpyle import LogManager, \ add_general_quantities, \ add_simulation_quantities, \ add_run_info if write_output: log_file_name = "wiggly.dat" else: log_file_name = None logmgr = LogManager(log_file_name, "w", rcon.communicator) add_run_info(logmgr) add_general_quantities(logmgr) add_simulation_quantities(logmgr) discr.add_instrumentation(logmgr) stepper.add_instrumentation(logmgr) logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"]) # timestep loop ----------------------------------------------------------- rhs = op.bind(discr) try: from grudge.timestep import times_and_steps step_it = times_and_steps( final_time=4, logmgr=logmgr, max_dt_getter=lambda t: op.estimate_timestep( discr, stepper=stepper, t=t, fields=fields)) for step, t, dt in step_it: if step % 10 == 0 and write_output: visf = vis.make_file("fld-%04d" % step) vis.add_data(visf, [ ("u", fields[0]), ("v", fields[1:]), ], time=t, step=step) visf.close() fields = stepper(fields, t, dt, rhs) assert discr.norm(fields) < 1 assert fields[0].dtype == dtype finally: if write_output: vis.close() logmgr.close() discr.close()