-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
InteriorBasis.point_source #632
Conversation
@@ -154,6 +154,10 @@ def probes(self, x: ndarray) -> coo_matrix: | |||
shape=(x.shape[1], self.N), | |||
) | |||
|
|||
def point_source(self, x: ndarray) -> ndarray: | |||
"""Return right-hand side vector for unit source at `x`""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this docstring true for other than Lagrange elements?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think so, in the Galerkin sense. Initially I reread Jan's point-source function in #561 and was reminded of what we'd done for the probe for Nico. Then i thought that at the continous variational level, interpolation is the inner product of a finite element function with a Dirac delta and a point source is the inner product of a Dirac delta with a test function. Those are adjoints and on discretization they're transposes. That line of thoight doesn't make any reference to the txpe of basis.
Similarly for skfem.models.poisson.unit_load
and the functional that integrates, replacing the Dirac delta with the constant 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a reference for this. I couldn't find one in a quick look. I remember that for years users were asking about point sources on other finite element msiling lists. Somtimes the discussion suggested mollification: convolving the point source with a Gaussian kernel, but I didn't like that so much as it still didn't seem well suited to the quadrature. Then FreeFEM added one recently; I refrained from looking at their implementation as it's GPL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible hole in the argument: the argument shows that the transpose property holds but it only follows from that that the function returns the Galerkin point source vector if the probes function works correctly. I didn't look into whether that works for all kinds of bases. Does it? I assumed that it did.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of brief references to point sources in some of the older FEM books on my self:
- Segerlind, L. J. (1976). Applied Finite Element Analysis. New York: Wiley, §8.6 ‘Point sources’
- Hughes, T. J. R. (2000). The Finite Element Method. Mineola, New York: Dover, exercise 3.11.2(b)
Unfortunately Hughes doesn't give the solution to the exercise (delta function loading on a one-dimensional, quadratic, three-node element), but I think it's looking the similar to my pair of linear two-node elements.
Segerlind notes:
The integral of a function multiplied by an impulse function, however, is simply the function evaluated at X0 and Y0.
which is elementary and the subsequent example is only for ElementTriP1
.
I'm yet to turn up anything on nonlagrangian elements.
from pathlib import Path
import numpy as np
import skfem
from skfem.models import laplace
from skfem.visuals.matplotlib import plot, savefig
mesh = skfem.MeshLine(np.linspace(0, 1, 2 ** 1 + 1))
basis = skfem.InteriorBasis(mesh, skfem.ElementLineHermite())
lap = skfem.asm(laplace, basis)
print(lap.toarray())
a = 3 / 4
rhs = basis.point_source(np.array([a]))
print("RHS:", rhs)
condensed = skfem.condense(lap, rhs, D=basis.find_dofs())
print(condensed[0].toarray())
print(condensed[1])
solution = skfem.solve(*condensed)
print(solution)
ax = plot(basis, solution, Nrefs=3)
ax.set_title(f"{type(basis.elem)}")
x = np.linspace(mesh.p[0].min(), mesh.p[0].max())
ax.plot(x, np.stack([(1 - a) * x, (1 - x) * a]).min(0), linestyle="--", label="exact")
ax.plot(
mesh.p[0],
solution[basis.nodal_dofs[0]],
marker="o",
linestyle="None",
label="nodal DoFs",
)
ax.legend()
savefig(Path(__file__).with_suffix(".png")) I think that that's doing the right thing. The scikit-fem/docs/examples/ex34.py Line 47 in 13b5d69
|
Perhaps I'll look at the elastic plate with from skfem import *
from skfem.helpers import ddot, dd
import numpy as np
mesh = MeshTri.init_circle(4)
element = ElementTriMorley()
mapping = MappingAffine(mesh)
ib = InteriorBasis(mesh, element, mapping, 2)
@BilinearForm
def biharmonic(u, v, w):
return ddot(dd(u), dd(v))
stokes = asm(biharmonic, ib)
psi = solve(*condense(stokes, ib.point_source(np.array([0.2, 0.3])), D=ib.find_dofs()))
if __name__ == "__main__":
from os.path import splitext
from sys import argv
from skfem.visuals.matplotlib import draw, show
from matplotlib.tri import Triangulation
M, Psi = ib.refinterp(psi, 3)
ax = draw(mesh)
ax.tricontour(Triangulation(*M.p, M.t.T), Psi)
name = splitext(argv[0])[0]
show() |
Looks good. Ready for merge or still a draft? |
I've actually used this kind of load in some of the articles on Kirchhoff plates and always hacked it together in nonreusable way. This would've really simplified that. Thanks! |
I should add a test. I'll add a comparison with the Green's function to the example later. I assume the Green's function for the Kirchhoff plate is known too. Have you got a reference to hand? Actually that might make a nicer example than the membrane, showing right away that it works for other than Lagrange elements. |
I think there is but I have no reference at hand. On the other hand, there is an infinite series solution available for a square plate and a point load. The series is not converging very quickly but it's something if you truncate it to a sum. See Section 5.1 (eq. 5.13) in this preprint: https://arxiv.org/pdf/1707.08396.pdf |
|
There is |
Let's take that up in #633. |
Let me add, |
It remains to include the example in |
I still haven't been able to find a better reference for the Green's function (Sadybekov et al just quote the result without reference or derivation), but this is it anyway. |
The PNG above will do for the Gallery. |
Sure! Can you add it to |
Fix #629 and exemplify.
This won't work for
MeshLine
until #628 is resolved, but is fine forMeshTri
, &c.Should probably compare the finite element solution with Green's function, as discussed in the docstring. For a test, I'd suggest one dimension, pending #628.