Skip to main content

differential equations - Numerically Solving Helmholtz over the Rectangle - Why does this code only give eigenfunctions of the form um1



I have been following the method for numerically solving the Helmholtz equation in this example (the answer by User21) and have come across two problems. I have been implementing the method for a 2x1 rectangle domain. The code I have used is as follows:


 Needs["NDSolve`FEM`"]


boundaryMesh =
ToBoundaryMesh[Polygon[{{1, 1/2}, {1, -1/2}, {-1, -1/2}, {-1, 1/2}}]]
boundaryMesh["Wireframe"]


mesh = ToElementMesh[boundaryMesh, "MeshOrder" -> 1,
"MaxCellMeasure" -> 0.001];
mesh["Wireframe"]


k = 1/10;
pde = D[u[t, x, y], t] - Laplacian[u[t, x, y], {x, y}] +
k^2 u[t, x, y] == 0;
\[CapitalGamma] = DirichletCondition[u[t, x, y] == 0, True];


nr = ToNumericalRegion[mesh];
{state} =
NDSolve`ProcessEquations[{pde, \[CapitalGamma], u[0, x, y] == 0},
u, {t, 0, 1}, {x, y} \[Element] nr];

femdata = state["FiniteElementData"]

initBCs = femdata["BoundaryConditionData"];
methodData = femdata["FEMMethodData"];

initCoeffs = femdata["PDECoefficientData"];


vd = methodData["VariableData"];
sd = NDSolve`SolutionData[{"Space" -> nr, "Time" -> 0.}];


discretePDE = DiscretizePDE[initCoeffs, methodData, sd];
discreteBCs = DiscretizeBoundaryConditions[initBCs, methodData, sd];



load = discretePDE["LoadVector"];
stiffness = discretePDE["StiffnessMatrix"];
damping = discretePDE["DampingMatrix"];


DeployBoundaryConditions[{load, stiffness, damping}, discreteBCs]


nDiri = First[Dimensions[discreteBCs["DirichletMatrix"]]];


numEigenToCompute = 5;
numEigen = numEigenToCompute + nDiri;


res = Eigensystem[{stiffness, damping}, -numEigen];
res = Reverse /@ res;
eigenValues = res[[1, nDiri + 1 ;; Abs[numEigen]]];
eigenVectors = res[[2, nDiri + 1 ;; Abs[numEigen]]];
(*res=Null;*)



evIF = ElementMeshInterpolation[{mesh}, #] & /@ eigenVectors;

I then plot the 2nd eigenfunction (for example) using:


Plot3D[Evaluate[evIF[[2]][x, y]], {x, y} \[Element] mesh, 
PlotRange -> All, Axes -> None, ViewPoint -> {0, -2, 1.5},
Boxed -> False, BoxRatios -> {1, 1, 1/4}, ImageSize -> 612,
Mesh -> All]


and I have (attempted) to plot the nodal lines of the eigenfunction using:


ContourPlot[Evaluate[evIF[[2]][x, y]]==0, {x, y} ∈ mesh, 
PlotRange -> All, Axes -> None, ImageSize -> 612,
PlotPoints -> 40]

The first problem is this:


It is well known that the nodal lines of the rectangle have the form umn, but the code seems to only give the eigenfunctions for um1 (n is fixed at 1) [see the below image]. I would be really grateful if somebody could tell me why this is happening. I am just starting to learn the basics of mathematica, so my knowledge is quite limited. I have been reading over the code but cannot seem to understand why it produces only eigenvalues of this form. In the image below, you can see that the code fails to produce eigenfunctions for u12, u21 and u13.


Eigenfunctions


The second issue is not so much of a problem, but more myself seeking some advice from the experts. Basically, I would like to know whether my contour plot for the nodal lines is the best way to approach this task. I have naively asked Mathematica to plot when the eigenfunction vanishes. Is there a better way of doing this?


I am very new to mathematica and I am not the most experienced of individuals when it comes to mathematics. Hence, if there are obvious flaws in my understanding of mathematica, or the mathematical material, then I would be more than happy for you to point them out.



I look forward to reading your responses.




Comments

Popular posts from this blog

mathematical optimization - Minimizing using indices, error: Part::pkspec1: The expression cannot be used as a part specification

I want to use Minimize where the variables to minimize are indices pointing into an array. Here a MWE that hopefully shows what my problem is. vars = u@# & /@ Range[3]; cons = Flatten@ { Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; Minimize[{Total@((vec1[[#]] - vec2[[u[#]]])^2 & /@ Range[1, 3]), cons}, vars, Integers] The error I get: Part::pkspec1: The expression u[1] cannot be used as a part specification. >> Answer Ok, it seems that one can get around Mathematica trying to evaluate vec2[[u[1]]] too early by using the function Indexed[vec2,u[1]] . The working MWE would then look like the following: vars = u@# & /@ Range[3]; cons = Flatten@{ Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; NMinimize[ {Total@((vec1[[#]] - Indexed[vec2, u[#]])^2 & /@ R...

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

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}]