I have searched other threads, but I was not successful in finding an answer I could understand.
Right to the point: how do I impose correctly periodic behavior on the edges of the rectangular region without knowing what the behavior is (using FEM in Mathematica)?
Minimal problem in 2D:
I am beginning to work with the new FEM in Mathematica 10 and I am interested in solving problems in pure space (no time, or just stationary if you want) with periodic space conditions for the unknown field in a rectangular regions. I am trying to solve the following minimal problem, but there is something I am missing and I dont get what.
Needs["NDSolve`FEM`"]
reg = ImplicitRegion[0 < 1, {{x1, 0, 1}, {x2, 0, 1}}];
eq0 = -Laplacian[u[x1, x2], {x1, x2}] - 10 x1^5*x2^3;
ucorner = 0;
(*
uedgex1 = (x1 - 1/2)^2 - 1/4;
uedgex2 = (x2 - 1/2)^2 - 1/4;
*)
conds = {
(*corners*)
DirichletCondition[u[x1, x2] == ucorner, x1 == 0 && x2 == 0]
, DirichletCondition[u[x1, x2] == ucorner, x1 == 1 && x2 == 0]
, DirichletCondition[u[x1, x2] == ucorner, x1 == 0 && x2 == 1]
, DirichletCondition[u[x1, x2] == ucorner, x1 == 1 && x2 == 1]
};
(*edges*)
(*
, DirichletCondition[u[x1, x2] == uedgex1, 0 < x1 < 1 && x2 == 0]
, DirichletCondition[u[x1, x2] == uedgex1, 0 < x1 < 1 && x2 == 1]
, DirichletCondition[u[x1, x2] == uedgex2, x1 == 0 && 0 < x2 < 1]
, DirichletCondition[u[x1, x2] == uedgex2, x1 == 1 && 0 < x2 < 1]
*)
ufem = NDSolveValue[{eq0 == 0, conds}, u, Element[{x1, x2},reg]];
Plot3D[ufem[x1, x2], Element[{x1, x2},reg], PlotRange -> All, AxesLabel -> {x1, x2}]
If you solve the problem imposing the behavior on the edges, of course you will get this and the solution is periodic in x1 and x2 (u[0,x2] = u[1,x2] for all x2, corresponding edge behavior is identical, but I just impose it).
Without imposing anything on the edges you will get this solution (of course not periodic in x1 or x2, u[x1,0] != u[x1,1] for all x1 and u[0,x2] != u[1,x2] for all x2)
Again my question: how do I impose correctly periodic behavior on the edges of the rectangular region without knowing what the behavior is (using FEM in Mathematica)? I have tried to impose the Dirichlet conditions like
DirichletCondition[u[x1, x2] == u[x1, 0], x2 == 1]
but they are not accepted. What am I missing? Thank you very much for an answer, the correct working code or any link to where I cam find my mistake. Greets
Mauricio
EDIT 1:
Thank you user21, I took a look into the documentation (its really awesome!!) and until now I have understood the following:
(*Obtain FEM state*)
{state} = NDSolve`ProcessEquations[{eq0 == 0, conds}, u, Element[{x1, x2}, nr], Method -> {"FiniteElement", "MeshOptions" -> {"MaxCellMeasure" -> 0.2}, "InterpolationOrder" -> {u -> 2}, "IntegrationOrder" -> 2}];
femstate = state["FiniteElementData"];
(********************************************)
(*Set everything manually*)
(*Unknown field, numerical region and mesh*)
vd = NDSolve`VariableData[{"DependentVariable" -> {u}, "Space" -> {x1, x2}}];
nr = ToNumericalRegion[Rectangle[{0, 0}, {1, 1}]];
mesh = ToElementMesh[nr, "MaxCellMeasure" -> 0.2];
plmesh = Show[mesh["Wireframe"["MeshElement" -> "MeshElements","MeshElementIDStyle" -> Blue, "ContinuousElementID" -> True]],mesh["Wireframe"["MeshElement" -> "PointElements","MeshElementIDStyle" -> Red]]];
(*Solution data*)
sd = NDSolve`SolutionData[{"Space" -> nr}];
(*Settings*)
methodData = InitializePDEMethodData[vd, sd, Method -> {"FiniteElement", "InterpolationOrder" -> {u -> 2}, "IntegrationOrder" -> 2}]
(*Initialize PDE coeffs, BCs, discretize system and get system matrices*)
initCoeff = femstate["PDECoefficientData"];
initBCs = InitializeBoundaryConditions[vd, sd, {conds}];
discretePDE = DiscretizePDE[initCoeff, methodData, sd];
stiffness = discretePDE["StiffnessMatrix"];
load = discretePDE["LoadVector"];
discreteBCs = DiscretizeBoundaryConditions[initBCs, methodData, sd];
DeployBoundaryConditions[{load, stiffness}, discreteBCs]
(*Solution, interpolation function and plot*)
solution = LinearSolve[stiffness, load];
uif = ElementMeshInterpolation[{mesh}, solution];
plsol = Plot3D[uif[x1, x2], {x1, x2} \[Element] mesh];
GraphicsRow[{plmesh,plsol}]
All commands are very clear but my last problem now is how to extract in an elegant form the node numbers on the edges without the corners (value on the corners imposed in Dirichlet conditions) and directly connect the corresponding nodes on the opposite edge. Until now I have used the following awful code, but I cannot think of anything smarter at the moment (it's 5 am :D). Any thoughts? (I mean, later I will try to use this for 3D rectangles and my approach is of course the most horrible way to do it). After that I would use the Lagrange multipliers as you explained.
mcoo = mesh["Coordinates"];
belnum = mesh["BoundaryElements"][[1, 1]] //Flatten //DeleteDuplicates;
belinfo = Table[{belnum[[i]], mcoo[[belnum[[i]]]]}, {i, Length[belnum]}];
(*Get corner nodes*)
c00 = Position[belinfo[[;; , 2]], {0., 0.}][[1, 1]];
n00 = belinfo[[c00, 1]];
c01 = Position[belinfo[[;; , 2]], {0., 1.}][[1, 1]];
n01 = belinfo[[c01, 1]];
c10 = Position[belinfo[[;; , 2]], {1., 0.}][[1, 1]];
n10 = belinfo[[c10, 1]];
c11 = Position[belinfo[[;; , 2]], {1., 1.}][[1, 1]];
n11 = belinfo[[c11, 1]];
Print["Corner nodes"]
ncs = {n00, n01, n10, n11}
(*Get first nodes on edge with x1=0 without corner nodes*)
infopos = Position[belinfo[[;; , 2, 1]], 0.] // Flatten;
edgex10 = belinfo[[infopos, 1]];
Do[edgex10 = DeleteCases[edgex10, ncs[[i]]], {i, Length[ncs]}]
Print["Edge with x1=0 without corner nodes"]
edgex10