Note
Go to the end to download the full example code.
Neumann condition for finite horizon kernel
The following example can be found at examples/example_Neumann.py in the PyNucleus repository.
where \(c(\delta)\) is the usual normalization constant.
where \(f\equiv 2\) and
The exact solution is \(u(x)=C-x^2\) where \(C\) is an arbitrary constant.
import numpy as np
import matplotlib.pyplot as plt
from PyNucleus import (nonlocalMeshFactory, dofmapFactory, kernelFactory,
functionFactory, solverFactory, NEUMANN, NO_BOUNDARY)
from PyNucleus_base.linear_operators import Dense_LinearOperator
Set up kernel, load $f$, the analytic solution and the flux data \(g\).
kernel = kernelFactory('constant', dim=1, horizon=0.4)
load = functionFactory('constant', 2.)
analyticSolution = functionFactory('Lambda', lambda x: -x[0]**2)
def fluxFun(x):
horizon = kernel.horizonValue
dist = 1+horizon-abs(x[0])
assert dist >= 0
return 2*kernel.scalingValue * (abs(x[0]) * (dist**2-horizon**2) + 1./3. * (dist**3+horizon**3))
flux = functionFactory('Lambda', fluxFun)
Construct a degree of freedom map for the entire mesh
mesh, nI = nonlocalMeshFactory('interval', kernel=kernel, boundaryCondition=NEUMANN)
for _ in range(3):
mesh = mesh.refine()
dm = dofmapFactory('P1', mesh, NO_BOUNDARY)
dm
P1 DoFMap with 57 DoFs and 0 boundary DoFs.
The second return value of the nonlocal mesh factory contains indicator functions:
dm.interpolate(nI['domain']).plot(label='domain')
dm.interpolate(nI['boundary']).plot(label='local boundary')
dm.interpolate(nI['interaction']).plot(label='interaction')
plt.legend()
<matplotlib.legend.Legend object at 0x7f50bd184bd0>
Assemble the RHS vector by using the load on the domain \(\Omega\) and the flux function on the interaction domain \(\Omega_\mathcal{I}\)
A = dm.assembleNonlocal(kernel)
b = dm.assembleRHS(load*nI['domain'] + flux*(nI['interaction']+nI['boundary']))
Solve the linear system. Since it is singular (shifts by a constant form the nullspace) we augment the system and then project out the zero mode.
u = dm.zeros()
Augment the system
correction = Dense_LinearOperator(np.ones(A.shape))
solver = solverFactory('lu', A=A+correction, setup=True)
solver(b, u)
1
project out the nullspace component
const = dm.ones()
u = u - (u.inner(const)/const.inner(const))*const
Interpolate the exact solution and project out zero mode as well.
uex = dm.interpolate(analyticSolution)
uex = uex - (uex.inner(const)/const.inner(const))*const
u.plot(label='numerical', marker='x')
uex.plot(label='analytic')
plt.legend()
<matplotlib.legend.Legend object at 0x7f50bd184810>
Total running time of the script: (0 minutes 0.127 seconds)