From 4b3392c593e908286a56de596c541a39731c5421 Mon Sep 17 00:00:00 2001 From: "[6~" <inform@tiker.net> Date: Tue, 12 May 2020 00:55:48 -0500 Subject: [PATCH] Simple DG solver works --- examples/simple-dg.py | 110 ++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 47 deletions(-) diff --git a/examples/simple-dg.py b/examples/simple-dg.py index dc780f26..8fe6f706 100644 --- a/examples/simple-dg.py +++ b/examples/simple-dg.py @@ -24,6 +24,7 @@ THE SOFTWARE. import numpy as np +import numpy.linalg as la # noqa import pyopencl as cl import pyopencl.array as cla # noqa import pyopencl.clmath as clmath @@ -33,7 +34,7 @@ from pytools.obj_array import ( with_object_array_or_scalar, is_obj_array) import loopy as lp -from meshmode.mesh import BTAG_ALL # noqa +from meshmode.mesh import BTAG_ALL, BTAG_NONE # noqa # Features lost vs. https://github.com/inducer/grudge: @@ -137,8 +138,12 @@ class DGDiscretization: return self.interior_faces_connection() elif src_tgt == ("vol", "all_faces"): return self.all_faces_connection() + elif src_tgt == ("vol", BTAG_ALL): + return self.boundary_connection(tgt) elif src_tgt == ("int_faces", "all_faces"): return self.get_to_all_face_embedding(src) + elif src_tgt == (BTAG_ALL, "all_faces"): + return self.get_to_all_face_embedding(src) else: raise ValueError(f"locations '{src}'->'{tgt}' not understood") @@ -156,6 +161,8 @@ class DGDiscretization: return self.all_faces_connection().to_discr elif where == "int_faces": return self.interior_faces_connection().to_discr + elif where == BTAG_ALL: + return self.boundary_connection(where).to_discr else: raise ValueError(f"location '{where}' not understood") @@ -215,7 +222,8 @@ class DGDiscretization: ((a,), (b,)) = with_queue( queue, parametrization_derivative(queue, bdry_discr)) - return without_queue(join_fields(b, -a)) + nrm = 1/(a**2+b**2)**0.5 + return without_queue(join_fields(b*nrm, -a*nrm)) @memoize_method def face_jacobian(self, where): @@ -241,7 +249,7 @@ class DGDiscretization: def inverse_mass(self, vec): if is_obj_array(vec): return with_object_array_or_scalar( - lambda el: self.face_mass(el), vec) + lambda el: self.inverse_mass(el), vec) @memoize_in(self, "elwise_linear_knl") def knl(): @@ -258,12 +266,12 @@ class DGDiscretization: discr = self.volume_discr - result = discr.empty(queue=self.queue, dtype=vec.dtype) + result = discr.empty(queue=vec.queue, dtype=vec.dtype) for grp in discr.groups: matrix = self.get_inverse_mass_matrix(grp, vec.dtype) - knl()(self.queue, mat=matrix, result=grp.view(result), + knl()(vec.queue, mat=matrix, result=grp.view(result), vec=grp.view(vec)) return result/self.vol_jacobian() @@ -318,6 +326,9 @@ class DGDiscretization: result = vol_discr.empty(queue=vec.queue, dtype=vec.dtype) + fj = self.face_jacobian("all_faces") + vec = vec*fj + assert len(all_faces_discr.groups) == len(vol_discr.groups) for afgrp, volgrp in zip(all_faces_discr.groups, vol_discr.groups): @@ -330,7 +341,7 @@ class DGDiscretization: knl()(vec.queue, mat=matrix, result=volgrp.view(result), vec=input_view) - return result*self.face_jacobian("all_faces") + return result # }}} @@ -410,24 +421,25 @@ def wave_operator(discr, c, w): u = w[0] v = w[1:] - # dir_u = discr.interp("vol", BTAG_ALL, u) - # dir_v = discr.interp("vol", BTAG_ALL, v) - # dir_bc = join_fields(-dir_u, dir_v) + dir_u = discr.interp("vol", BTAG_ALL, u) + dir_v = discr.interp("vol", BTAG_ALL, v) + dir_bval = join_fields(dir_u, dir_v) + dir_bc = join_fields(-dir_u, dir_v) - result = ( + return ( - join_fields( -c*discr.div(v), -c*discr.grad(u) ) - + # noqa: W504 - discr.inverse_mass( - discr.face_mass( - wave_flux(discr, c=c, w_tpair=interior_trace_pair(discr, w)) - #+ flux(sym.bv_tpair(self.dirichlet_tag, w, dir_bc)) - )) + + # noqa: W504 + discr.inverse_mass( + discr.face_mass( + wave_flux(discr, c=c, w_tpair=interior_trace_pair(discr, w)) + + wave_flux(discr, c=c, w_tpair=TracePair( + BTAG_ALL, dir_bval, dir_bc)) + )) ) - return result # }}} @@ -440,59 +452,63 @@ def rk4_step(y, t, h, f): return y + h/6*(k1 + 2*k2 + 2*k3 + k4) +def bump(discr, queue, t=0): + source_center = np.array([0.0, 0.05]) + source_width = 0.05 + source_omega = 3 + + nodes = discr.volume_discr.nodes().with_queue(queue) + center_dist = join_fields([ + nodes[0] - source_center[0], + nodes[1] - source_center[1], + ]) + + return ( + np.cos(source_omega*t) + * clmath.exp( + -np.dot(center_dist, center_dist) + / source_width**2)) + + def main(): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) + nel_1d = 16 from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh( a=(-0.5, -0.5), b=(0.5, 0.5), - n=(16, 16)) + n=(nel_1d, nel_1d)) + + order = 3 - dt = 0.04 + # no deep meaning here, just a fudge factor + dt = 0.75/(nel_1d*order**2) print("%d elements" % mesh.nelements) - discr = DGDiscretization(cl_ctx, mesh, order=4) + discr = DGDiscretization(cl_ctx, mesh, order=order) - fields = join_fields(discr.zeros(queue), - [discr.zeros(queue) for i in range(discr.dim)]) + fields = join_fields( + bump(discr, queue), + [discr.zeros(queue) for i in range(discr.dim)] + ) from meshmode.discretization.visualization import make_visualizer - vis = make_visualizer(queue, discr.volume_discr, discr.order) - - source_center = np.array([0.0, 0.05]) - source_width = 0.05 - source_omega = 3 + vis = make_visualizer(queue, discr.volume_discr, discr.order+3) def rhs(t, w): - queue = w[0].queue - - nodes = discr.volume_discr.nodes().with_queue(queue) - center_dist = join_fields([ - nodes[0] - source_center[0], - nodes[1] - source_center[1], - ]) - - source_f = ( - np.sin(source_omega*t) - * clmath.exp( - -np.dot(center_dist, center_dist) - / source_width**2)) - result = wave_operator(discr, c=1, w=w) - if t < 0.3: - result[0] = result[0] + source_f - - return result + return wave_operator(discr, c=1, w=w) t = 0 - t_final = 5 + t_final = 3 istep = 0 while t < t_final: fields = rk4_step(fields, t, dt, rhs) - if istep % 2 == 0: + if istep % 10 == 0: + print(istep, t, la.norm(fields[0].get())) vis.write_vtk_file("fld-wave-min-%04d.vtu" % istep, [ ("u", fields[0]), -- GitLab