Quick StartΒΆ
Create a high-order quadrilateral sphere and check a Laplace-Beltrami identity:
import pysurfacefun as psf
dom = psf.sphere(n=9, nref=1)
u = psf.field(lambda x, y, z: x * y * z, dom)
print(psf.surfacearea(dom))
print(psf.norm(psf.lap(u) + 12*u, "inf"))
Solve a shifted surface Helmholtz problem:
alpha = 2.0
rhs = (alpha - 12.0) * u
problem = psf.SurfaceProblem(dom, variables="u", namespace={"alpha": alpha, "rhs": rhs})
problem.add_equation("lap(u) + alpha*u = rhs")
uh = problem.solve()
relerr = psf.norm(uh - u, "inf") / psf.norm(u, "inf")
print(relerr)
Triangular patches use the same style of interface:
dom = psf.icosphere_tri(n=10, nref=1)
u = psf.field(lambda x, y, z: x * y * z, dom)
print(psf.integral(psf.field(1.0, dom)))
print(psf.norm(psf.lap(u) + 12*u, "inf"))
Repeatable output for examples and notebooks:
evaluator = psf.Evaluator(
"notebook_outputs",
prefix="sphere_demo",
handlers=[
psf.JSONLinesOutputHandler(),
psf.NPZOutputHandler(),
psf.VTKOutputHandler(nvis=16),
],
)
evaluator.add_task("linf_residual", lambda state: psf.norm(psf.lap(state["u"]) + 12*state["u"], "inf"))
evaluator.add_task("u", lambda state: state["u"], every=10)
evaluator.evaluate(0, state={"u": u})
Implicit reaction-diffusion time stepping:
def reaction(u, t):
return u - 2.0*u**3
solver = psf.SurfaceIVP(u, diffusion=1e-3, reaction=reaction).build_solver(dt=0.05).build()
u = solver.run(20)