Skip to main content

differential equations - Least effort to handle a point source inside the domain of PDE(s)


By point source I mean a constrained condition at one point inside the domain of PDE(s). For example:


$$\frac{\partial ^2u(t,x,y)}{\partial t^2}=\frac{\partial ^2u(t,x,y)}{\partial x^2}+\frac{\partial ^2u(t,x,y)}{\partial y^2}$$ $$u(t,0,0)=\sin (10 t)$$ $$u(0,x,y)=0,u^{(1,0,0)}(0,x,y)=0$$ $$u(t,-1,y)=0,u(t,1,y)=0$$ $$u(t,x,-1)=0,u(t,x,1)=0$$ $$0\leq t\leq 3,-1\leq x\leq 1,-1\leq y\leq 1$$



This can model… Er… a square edge-fixed membrane with one tip of an ultra thin moving rod stuck on the center. The condition $u(t,0,0)=\sin (10 t)$ is exactly a point source. (Notice it's not completely compatible with the initial conditions but it's not a big deal. )


NDSolve can't solve this problem directly (at least now):


NDSolve[{
D[u[t, x, y], t, t] == D[u[t, x, y], x, x] + D[u[t, x, y], y, y],
u[t, 0, 0] == Sin[10 t],
u[0, x, y] == 0,
Derivative[1, 0, 0][u][0, x, y] == 0,
u[t, -1, y] == 0,
u[t, 1, y] == 0,
u[t, x, -1] == 0,

u[t, x, 1] == 0},
u, {t, 0, 3}, {x, -1, 1}, {y, -1, 1}]


NDSolve::bcedge: Boundary condition u[t,0,0]==Sin[t] is not specified on a single edge of the boundary of the computational domain. >>



Of course FDM can handle the point source naturally:


ans = (Reap@
With[{n = 50, c = 1},
With[{dx = (1 - (-1))/(n - 1), Courant = Sqrt[2]/2},

With[{dt = (Courant dx)/c},
Compile[{},
Module[{z1, z2}, z1 = z2 = Table[0., {n}, {n}];
Do[{z1, z2} = {z2, z1};
z1[[Ceiling[n/2], Ceiling[n/2]]] = Sin[10 t];
Do[z2[[i, j]] =
z1[[i, j]] + z1[[i, j]] - z2[[i, j]] +
Courant^2 (z1[[i - 1, j]] + z1[[i + 1, j]] +
z1[[i, j - 1]] + z1[[i, j + 1]] -
4 z1[[i, j]]), {i, 2, n - 1}, {j, 2, n - 1}];

Sow[z1], {t, 0, 3, dt}]]]]]][])[[-1, 1]];
ListPlot3D[#, Mesh -> False, PlotRange -> {-1, 1}] & /@ ans;
SystemOpen@Export["a.gif", %];

enter image description here


But can we more or less benefit from NDSolve or other existed tools in Mathematica, instead of doing something from scratch? Is NDSolve completely useless in this situation?


A general solution is the best, but opportunistic ones, I mean, solutions that are only suited for the specific example above are also welcomed!



Answer



The good news is that yes, there is an easy way to put your problem into NDSolve by using the new finite element functionality in v10. The bad news is that it seems the specific problem you're trying to solve is ill-posed.





NDSolve can now handle internal boundaries; see e.g. the first figure under "Details" for DirichletCondition. Generating a mesh with such internal boundaries is described in the "Element Mesh Generation" tutorial. I don't know if a single constrained point technically counts as a "boundary", but it seems to work.


Create a spatial mesh with a node at the point source:


Needs["NDSolve`FEM`"];
bmesh = ToBoundaryMesh[
"Coordinates" -> {{-1, -1}, {-1, 1}, {1, 1}, {1, -1}, {0, 0}},
"BoundaryElements" -> {LineElement[{{1, 2}, {2, 3}, {3, 4}, {4, 1}}]}];
mesh = ToElementMesh[bmesh];
Show[mesh["Wireframe"], Graphics[{Red, PointSize[Large], Point[{0, 0}]}]]

enter image description here



(One could also use the not-really-documented "IncludePoints" option, as in this other answer.)


Direcly specifying u[t, 0, 0] doesn't work, as you already know, but DirichletCondition does:


sol = NDSolve[{
D[u[t, x, y], t, t] == D[u[t, x, y], x, x] + D[u[t, x, y], y, y],
DirichletCondition[u[t, x, y] == Sin[10 t], x == 0 && y == 0],
u[0, x, y] == 0,
Derivative[1, 0, 0][u][0, x, y] == 0,
u[t, -1, y] == 0,
u[t, 1, y] == 0,
u[t, x, -1] == 0,

u[t, x, 1] == 0},
u, {t, 0, 3}, {x, y} ∈ mesh];

It complains that "NDSolve has computed initial values that give a zero residual for the differential-algebraic system, but some components are different from those specified", which is to be expected. But it gives a solution anyway.


frames = Table[
Plot3D[u[t, x, y] /. sol, {x, -1, 1}, {y, -1, 1},
PlotRange -> {-1, 1}, Mesh -> None, PlotStyle -> White], {t, 0, 3, 0.05}];
Export["a.gif", frames];

enter image description here





We start to see a problem if we change the resolution of the mesh. To avoid the massive memory requirements of a uniformly refined mesh, it's better to refine only where the solution changes rapidly, i.e. in the neighbourhood of the point source. One can use


mesh = ToElementMesh[bmesh, 
"MeshRefinementFunction" -> Function[{vertices, area},
area > Max[a, 1*^-2 Min[Norm /@ vertices]]]];

which smoothly refines the mesh to have elements of area $a$ near the point source at the origin. Here are some meshes with $a=10^{-2}$, $10^{-4}$, and $10^{-6}$, followed by zooms to $[-0.1,0.1]\times[-0.1,0.1]$:


enter image description here enter image description here enter image description here


enter image description here enter image description here enter image description here


And here are the corresponding solutions at $t=1$:



enter image description here enter image description here enter image description here


The solutions seem to be getting weaker the finer we make the mesh. What's going on? I don't know for absolutely certain, but I'm guessing that the problem is ill-posed and the solution we've computed is essentially an artifact of the numerical discretization. As an analogy, consider the Laplace problem on a punctured domain with Dirichlet boundary conditions: $$\begin{align} \nabla^2f(x,y)&=0&\text{for }&x\in\Omega\setminus\{(0,0)\},\\ f(x,y)&=0&\text{for }&x\in\partial\Omega,\\ f(0,0)&=1. \end{align}$$ You can solve this numerically and obtain a reasonable-looking numerical solution, but it is an illusion because a one-point set has zero capacity for the Laplacian, and if you refine the mesh the solution goes to zero. I believe the same thing is happening here. Numerically, the energy that the source imparts to the system is mesh-dependent, being related to the area of its neighbouring elements. Theoretically, I guess there is no solution.




So yeah. Can you use NDSolve for this problem? You can. But... maybe you shouldn't.


Disclaimer: I am not a functional analyst and this is not mathematical advice. Consult your friendly neighbourhood applied mathematician.


Comments

Popular posts from this blog

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Adding a thick curve to a regionplot

Suppose we have the following simple RegionPlot: f[x_] := 1 - x^2 g[x_] := 1 - 0.5 x^2 RegionPlot[{y < f[x], f[x] < y < g[x], y > g[x]}, {x, 0, 2}, {y, 0, 2}] Now I'm trying to change the curve defined by $y=g[x]$ into a thick black curve, while leaving all other boundaries in the plot unchanged. I've tried adding the region $y=g[x]$ and playing with the plotstyle, which didn't work, and I've tried BoundaryStyle, which changed all the boundaries in the plot. Now I'm kinda out of ideas... Any help would be appreciated! Answer With f[x_] := 1 - x^2 g[x_] := 1 - 0.5 x^2 You can use Epilog to add the thick line: RegionPlot[{y < f[x], f[x] < y < g[x], y > g[x]}, {x, 0, 2}, {y, 0, 2}, PlotPoints -> 50, Epilog -> (Plot[g[x], {x, 0, 2}, PlotStyle -> {Black, Thick}][[1]]), PlotStyle -> {Directive[Yellow, Opacity[0.4]], Directive[Pink, Opacity[0.4]],