def test_mean_curvature(ctx_factory, discr_name, resolutions, discr_and_ref_mean_curvature_getter, visualize=False): ctx = ctx_factory() queue = cl.CommandQueue(ctx) actx = PyOpenCLArrayContext(queue) from pytools.convergence import EOCRecorder eoc = EOCRecorder() for r in resolutions: discr, ref_mean_curvature = \ discr_and_ref_mean_curvature_getter(actx, r) mean_curvature = bind(discr, sym.mean_curvature(discr.ambient_dim))(actx) h = 1.0 / r from meshmode.dof_array import flat_norm h_error = flat_norm(mean_curvature - ref_mean_curvature, np.inf) eoc.add_data_point(h, h_error) print(eoc) order = min([g.order for g in discr.groups]) assert eoc.order_estimate() > order - 1.1
def operator(self, sigma): """ Returns the two second kind integral equations. """ rep = self.representation(sigma, qbx_forced_limit="avg") rep_diff = sym.normal_derivative(2, rep) int_eq1 = sigma[0] / 2 + rep int_eq2 = -sym.mean_curvature(2) * sigma[0] + sigma[1] / 2 + rep_diff return np.array([int_eq1, int_eq2])
def operator(self, sigma: sym.var, mean_curvature: Optional[sym.var] = None, **kwargs) -> sym.var: """ :arg mean_curvature: an expression for the mean curvature that can be used in the construction of the operator. :returns: a Fredholm integral equation of the second kind for the Beltrami PDE with the unknown density *sigma*. """ from sumpy.kernel import LaplaceKernel if isinstance(self.kernel, LaplaceKernel): raise TypeError( f"{type(self).__name__} does not support the Laplace " "kernel, use LaplaceBeltramiOperator instead") if mean_curvature is None: mean_curvature = sym.mean_curvature(self.ambient_dim, dim=self.dim) kappa = self.dim * mean_curvature context = self.kernel_arguments.copy() context.update(kwargs) knl = self.kernel lknl = LaplaceKernel(knl.dim) # {{{ layer potentials # laplace S0 = partial(sym.S, lknl, qbx_forced_limit=+1, **kwargs) # noqa: N806 D0 = partial(sym.D, lknl, qbx_forced_limit="avg", **kwargs) # noqa: N806 Sp0 = partial(sym.Sp, lknl, qbx_forced_limit="avg", **kwargs) # noqa: N806 Dp0 = partial(sym.Dp, lknl, qbx_forced_limit="avg", **kwargs) # noqa: N806 # base S = partial(sym.S, knl, qbx_forced_limit=+1, **context) # noqa: N806 Sp = partial(sym.Sp, knl, qbx_forced_limit="avg", **context) # noqa: N806 Spp = partial(sym.Spp, knl, qbx_forced_limit="avg", **context) # noqa: N806 # }}} if self.precond == "left": # similar to 6.2 in [ONeil2017] op = (sigma / 4 - D0(D0(sigma)) + S(kappa * Sp(sigma)) + S(Spp(sigma) + Dp0(sigma)) - S(Dp0(sigma)) + S0(Dp0(sigma))) else: # similar to 6.2 in [ONeil2017] op = (sigma / 4 - Sp0(Sp0(sigma)) + (Spp(S(sigma)) + Dp0(S(sigma))) - Dp0(S(sigma) - S0(sigma)) + kappa * Sp(S(sigma))) return op
def plot_solution(actx, vis, filename, discr, t, x): names_and_fields = [] try: from pytential import bind, sym kappa = bind(discr, sym.mean_curvature(discr.ambient_dim))(actx) names_and_fields.append(("kappa", kappa)) except ImportError: pass vis.write_vtk_file(filename, names_and_fields, overwrite=True)
def operator(self, sigma: sym.var, mean_curvature: Optional[sym.var] = None, **kwargs) -> sym.var: """ :arg mean_curvature: an expression for the mean curvature that can be used in the construction of the operator. :returns: a Fredholm integral equation of the second kind for the Laplace-Beltrami PDE with the unknown density *sigma*. """ if mean_curvature is None: mean_curvature = sym.mean_curvature(self.ambient_dim, dim=self.dim) kappa = self.dim * mean_curvature context = self.kernel_arguments.copy() context.update(kwargs) knl = self.kernel # {{{ layer potentials S = partial(sym.S, knl, qbx_forced_limit=+1, **context) # noqa: N806 Sp = partial(sym.Sp, knl, qbx_forced_limit="avg", **context) # noqa: N806 Spp = partial(sym.Spp, knl, qbx_forced_limit="avg", **context) # noqa: N806 D = partial(sym.D, knl, qbx_forced_limit="avg", **context) # noqa: N806 Dp = partial(sym.Dp, knl, qbx_forced_limit="avg", **context) # noqa: N806 def Wl(operand: sym.Expression) -> sym.Expression: # noqa: N802 return sym.Ones() * sym.integral(self.ambient_dim, self.dim, operand) def Wr(operand: sym.Expression) -> sym.Expression: # noqa: N802 return sym.Ones() * sym.integral(self.ambient_dim, self.dim, operand) # }}} if self.precond == "left": # NOTE: based on Lemma 3.1 in [ONeil2017] for :math:`-\Delta_\Gamma` op = (sigma / 4 - D(D(sigma)) + S(Spp(sigma) + Dp(sigma)) + S(kappa * Sp(sigma)) - S(Wl(S(sigma)))) else: # NOTE: based on Lemma 3.2 in [ONeil2017] for :math:`-\Delta_\Gamma` op = (sigma / 4 - Sp(Sp(sigma)) + (Spp(S(sigma)) + Dp(S(sigma))) + kappa * Sp(S(sigma)) + Wr(S(S(sigma)))) return op
def operator(self, sigma, **kwargs): """ :param u: symbolic variable for the density. :param kwargs: additional keyword arguments passed on to the layer potential constructor. :returns: the second kind integral operator for the clamped plate problem from [Farkas1990]_. """ rep = self.representation(sigma, qbx_forced_limit="avg", **kwargs) drep_dn = sym.normal_derivative(self.dim, rep) int_eq1 = sigma[0] / 2 + rep int_eq2 = -sym.mean_curvature(self.dim) * sigma[0] + sigma[1] / 2 + drep_dn return np.array([int_eq1, int_eq2])
fig.savefig(f"{filename}_y") plt.close(fig) else: from meshmode.discretization.visualization import make_visualizer vis = make_visualizer(actx, density_discr, vis_order=case.target_order, force_equidistant=True) ref_error = actx.np.abs(result - ref_result) + 1.0e-16 from pytential.symbolic.primitives import _scaled_max_curvature scaled_kappa = bind(places, _scaled_max_curvature(places.ambient_dim), auto_where=case.name)(actx) kappa = bind(places, sym.mean_curvature(places.ambient_dim), auto_where=case.name)(actx) vis.write_vtk_file(f"{filename}.vtu", [ ("result", result), ("ref", ref_result), ("error", ref_error), ("log_error", actx.np.log10(ref_error)), ("kappa", kappa - 1.0), ("scaled_kappa", scaled_kappa), ], use_high_order=True, overwrite=True) return h_max, error class StokesletIdentity: