def main(write_output=True): from grudge.data import GivenFunction, ConstantGivenFunction from grudge.backends import guess_run_context rcon = guess_run_context() dim = 2 def boundary_tagger(fvi, el, fn, points): from math import atan2, pi normal = el.face_normals[fn] if -90/180*pi < atan2(normal[1], normal[0]) < 90/180*pi: return ["neumann"] else: return ["dirichlet"] def dirichlet_boundary_tagger(fvi, el, fn, points): return ["dirichlet"] if dim == 2: if rcon.is_head_rank: from grudge.mesh.generator import make_disk_mesh mesh = make_disk_mesh(r=0.5, boundary_tagger=dirichlet_boundary_tagger, max_area=1e-3) elif dim == 3: if rcon.is_head_rank: from grudge.mesh.generator import make_ball_mesh mesh = make_ball_mesh(max_volume=0.0001, boundary_tagger=lambda fvi, el, fn, points: ["dirichlet"]) else: raise RuntimeError("bad number of dimensions") if rcon.is_head_rank: 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=5, debug=[]) def dirichlet_bc(x, el): from math import sin return sin(10*x[0]) def rhs_c(x, el): if la.norm(x) < 0.1: return 1000 else: return 0 def my_diff_tensor(): result = numpy.eye(dim) result[0,0] = 0.1 return result try: from grudge.models.poisson import ( PoissonOperator, HelmholtzOperator) from grudge.second_order import \ IPDGSecondDerivative, LDGSecondDerivative, \ StabilizedCentralSecondDerivative k = 1 from grudge.mesh import BTAG_NONE, BTAG_ALL op = HelmholtzOperator(k, discr.dimensions, #diffusion_tensor=my_diff_tensor(), #dirichlet_tag="dirichlet", #neumann_tag="neumann", dirichlet_tag=BTAG_ALL, neumann_tag=BTAG_NONE, #dirichlet_tag=BTAG_ALL, #neumann_tag=BTAG_NONE, #dirichlet_bc=GivenFunction(dirichlet_bc), dirichlet_bc=ConstantGivenFunction(0), neumann_bc=ConstantGivenFunction(-10), scheme=StabilizedCentralSecondDerivative(), #scheme=LDGSecondDerivative(), #scheme=IPDGSecondDerivative(), ) bound_op = op.bind(discr) if False: from grudge.iterative import parallel_cg u = -parallel_cg(rcon, -bound_op, bound_op.prepare_rhs(discr.interpolate_volume_function(rhs_c)), debug=20, tol=5e-4, dot=discr.nodewise_dot_product, x=discr.volume_zeros()) else: rhs = bound_op.prepare_rhs(discr.interpolate_volume_function(rhs_c)) def compute_resid(x): return bound_op(x)-rhs from scipy.sparse.linalg import minres, LinearOperator u, info = minres( LinearOperator( (len(discr), len(discr)), matvec=bound_op, dtype=bound_op.dtype), rhs, callback=ResidualPrinter(compute_resid), tol=1e-5) print() if info != 0: raise RuntimeError("gmres reported error %d" % info) print("finished gmres") print(la.norm(bound_op(u)-rhs)/la.norm(rhs)) if write_output: from grudge.visualization import SiloVisualizer, VtkVisualizer vis = VtkVisualizer(discr, rcon) visf = vis.make_file("fld") vis.add_data(visf, [ ("sol", discr.convert_volume(u, kind="numpy")), ]) visf.close() finally: discr.close()
def main(write_output=True) : from math import sin, cos, pi, exp, sqrt from grudge.data import TimeConstantGivenFunction, \ ConstantGivenFunction from grudge.backends import guess_run_context rcon = guess_run_context() dim = 2 def boundary_tagger(fvi, el, fn, all_v): if el.face_normals[fn][0] > 0: return ["dirichlet"] else: return ["neumann"] if dim == 2: if rcon.is_head_rank: from grudge.mesh.generator import make_disk_mesh mesh = make_disk_mesh(r=0.5, boundary_tagger=boundary_tagger) elif dim == 3: if rcon.is_head_rank: from grudge.mesh.generator import make_ball_mesh mesh = make_ball_mesh(max_volume=0.001) else: raise RuntimeError("bad number of dimensions") if rcon.is_head_rank: 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=3, debug=["cuda_no_plan"], default_scalar_type=numpy.float64) if write_output: from grudge.visualization import VtkVisualizer vis = VtkVisualizer(discr, rcon, "fld") def u0(x, el): if la.norm(x) < 0.2: return 1 else: return 0 def coeff(x, el): if x[0] < 0: return 0.25 else: return 1 def dirichlet_bc(t, x): return 0 def neumann_bc(t, x): return 2 from grudge.models.diffusion import DiffusionOperator op = DiffusionOperator(discr.dimensions, #coeff=coeff, dirichlet_tag="dirichlet", dirichlet_bc=TimeConstantGivenFunction(ConstantGivenFunction(0)), neumann_tag="neumann", neumann_bc=TimeConstantGivenFunction(ConstantGivenFunction(1)) ) u = discr.interpolate_volume_function(u0) # diagnostics setup ------------------------------------------------------- from logpyle import LogManager, \ add_general_quantities, \ add_simulation_quantities, \ add_run_info if write_output: log_file_name = "heat.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) from grudge.log import LpNorm u_getter = lambda: u logmgr.add_quantity(LpNorm(u_getter, discr, 1, name="l1_u")) logmgr.add_quantity(LpNorm(u_getter, discr, name="l2_u")) logmgr.add_watches(["step.max", "t_sim.max", "l2_u", "t_step.max"]) # timestep loop ----------------------------------------------------------- from grudge.timestep.runge_kutta import LSRK4TimeStepper, ODE45TimeStepper from grudge.timestep.dumka3 import Dumka3TimeStepper #stepper = LSRK4TimeStepper() stepper = Dumka3TimeStepper(3, rtol=1e-6, rcon=rcon, vector_primitive_factory=discr.get_vector_primitive_factory(), dtype=discr.default_scalar_type) #stepper = ODE45TimeStepper(rtol=1e-6, rcon=rcon, #vector_primitive_factory=discr.get_vector_primitive_factory(), #dtype=discr.default_scalar_type) stepper.add_instrumentation(logmgr) rhs = op.bind(discr) try: next_dt = op.estimate_timestep(discr, stepper=LSRK4TimeStepper(), t=0, fields=u) from grudge.timestep import times_and_steps step_it = times_and_steps( final_time=0.1, logmgr=logmgr, max_dt_getter=lambda t: next_dt, taken_dt_getter=lambda: taken_dt) 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", discr.convert_volume(u, kind="numpy")), ], time=t, step=step) visf.close() u, t, taken_dt, next_dt = stepper(u, t, next_dt, rhs) #u = stepper(u, t, dt, rhs) assert discr.norm(u) < 1 finally: if write_output: vis.close() logmgr.close() discr.close()
def __init__(self, dimensions, gamma=None, mu=0, bc_inflow=None, bc_outflow=None, bc_noslip=None, bc_supersonic_inflow=None, prandtl=None, spec_gas_const=1.0, equation_of_state=None, inflow_tag="inflow", outflow_tag="outflow", noslip_tag="noslip", wall_tag="wall", supersonic_inflow_tag="supersonic_inflow", supersonic_outflow_tag="supersonic_outflow", source=None, second_order_scheme=CentralSecondDerivative(), artificial_viscosity_mode=None, ): """ :param source: should implement :class:`grudge.data.IFieldDependentGivenFunction` or be None. :param artificial_viscosity_mode: """ from grudge.data import ( TimeConstantGivenFunction, ConstantGivenFunction) if gamma is not None: if equation_of_state is not None: raise ValueError("can only specify one of gamma and equation_of_state") from warnings import warn warn("argument gamma is deprecated in favor of equation_of_state", DeprecationWarning, stacklevel=2) equation_of_state = GammaLawEOS(gamma) dull_bc = TimeConstantGivenFunction( ConstantGivenFunction(make_obj_array( [1, 1] + [0]*dimensions))) if bc_inflow is None: bc_inflow = dull_bc if bc_outflow is None: bc_outflow = dull_bc if bc_noslip is None: bc_noslip = dull_bc if bc_supersonic_inflow is None: bc_supersonic_inflow = dull_bc self.dimensions = dimensions self.prandtl = prandtl self.spec_gas_const = spec_gas_const self.mu = mu self.bc_inflow = bc_inflow self.bc_outflow = bc_outflow self.bc_noslip = bc_noslip self.bc_supersonic_inflow = bc_supersonic_inflow self.inflow_tag = inflow_tag self.outflow_tag = outflow_tag self.noslip_tag = noslip_tag self.wall_tag = wall_tag self.supersonic_inflow_tag = supersonic_inflow_tag self.supersonic_outflow_tag = supersonic_outflow_tag self.source = source self.equation_of_state = equation_of_state self.second_order_scheme = second_order_scheme if artificial_viscosity_mode not in [ "cns", "diffusion", "blended", None]: raise ValueError("artificial_viscosity_mode has an invalid value") self.artificial_viscosity_mode = artificial_viscosity_mode