7

I want to use ElementMeshInterpolation to generate interpolation function with periodic boundary condition.

I use below data as an example

data=Flatten[Table[{i,j,Sin[i+j]},{i,0,2\[Pi],2\[Pi]/50},{j,0,2\[Pi],2\[Pi]/50}],1];
ListContourPlot[data]

which gives

enter image description here

This data is periodic along x and y direction.

Using Interpolation

f = Interpolation[data, PeriodicInterpolation -> True];
{ContourPlot[f[x, y], {x, 0, 2 \[Pi]}, {y, 0, 2 \[Pi]}], 
 ContourPlot[f[x, y], {x, 0, 4 \[Pi]}, {y, 0, 4 \[Pi]}]}

gives

enter image description here

We can see the Interpolation function is fine with periodic condition as wanted.

using ElementMeshInterpolation

Though Interpolation works fine for this data set. But Interpolation has problem that it frequently run into "femimq" problem. So ElementMeshInterpolation on a refined mesh is necessary sometimes.

mesh = ToElementMesh[data[[;; , 1 ;; 2]]];
f = ElementMeshInterpolation[{mesh}, data[[;; , -1]], 
   PeriodicInterpolation -> {True, True}];
{ContourPlot[f[x, y], {x, 0, 2 \[Pi]}, {y, 0, 2 \[Pi]}], 
 ContourPlot[f[x, y], {x, 0, 4 \[Pi]}, {y, 0, 4 \[Pi]}]}

this gives

enter image description here

You see the generated Interpolation function has no periodicity.

using ListInterpolation

mesh can also be used in ListInterpolation

mesh = ToElementMesh[data[[;; , 1 ;; 2]]];
f = ListInterpolation[data[[;; , -1]], mesh, 
   PeriodicInterpolation -> {True, True}];
{ContourPlot[f[x, y], {x, 0, 2 \[Pi]}, {y, 0, 2 \[Pi]}], 
 ContourPlot[f[x, y], {x, 0, 4 \[Pi]}, {y, 0, 4 \[Pi]}]}

but this gives the same result as ElementMeshInterpolation.

So the question is how to correctly make periodic interpolation function using ElementMeshInterpolation.

user21
  • 39,710
  • 8
  • 110
  • 167
matheorem
  • 17,132
  • 8
  • 45
  • 115

2 Answers2

10

You can not really. The fact that Interpolation can do this hinges on the data being structured. In other works what I am going to show next is not easily generally possible for meshes that represent a non rectangullar domain; which is the common case for FEM meshes.

You can hack it by using the ExtrapolationHandler option.

    Needs["NDSolve`FEM`"]
    data = Flatten[
       Table[{i, j, Sin[i + j]}, {i, 0, 2 \[Pi], 2 \[Pi]/50}, {j, 0, 
         2 \[Pi], 2 \[Pi]/50}], 1];
    mesh = ToElementMesh[data[[;; , 1 ;; 2]]];
    f = ElementMeshInterpolation[{mesh}, data[[;; , -1]]];

Now, we can use f as a function in the extrapolation handler and map the coordinates outside the domain back onto f. This mapping back to the original domain is tricky to do generally. Here we use Mod.

    f2 = ElementMeshInterpolation[{mesh}, data[[;; , -1]], 
      "ExtrapolationHandler" -> {Function[{x, y}, 
         f[Mod[x, 2 \[Pi]], Mod[y, 2 \[Pi]]]]}]

{ContourPlot[f2[x, y], {x, 0, 2 [Pi]}, {y, 0, 2 [Pi]}], ContourPlot[f2[x, y], {x, 0, 4 [Pi]}, {y, 0, 4 [Pi]}]}

plots

If you want to switch of the warning message you can do so with:

f2 = ElementMeshInterpolation[{mesh}, data[[;; , -1]], 
  "ExtrapolationHandler" -> {Function[{x, y}, 
     f[Mod[x, 2 \[Pi]], Mod[y, 2 \[Pi]]]], "WarningMessage" -> False}]

Perhaps an idea for a future implementation.

user21
  • 39,710
  • 8
  • 110
  • 167
  • 1
    Thank you so much. I am interested in the overhead of "ExtrapolationHandler". I found a peculiar thing. The ContourPlot of f2 is even faster than f. However, Table[Quiet@f2[x,y],{x,100.,150.,1},{y,100.,150.,1}];//AbsoluteTiming is much slower than Table[f[x,y],{x,100.,150.,1},{y,100.,150.,1}];//AbsoluteTiming. Why is that? – matheorem Feb 04 '21 at 08:22
  • And what do you mean by "Interpolation can do this hinges on the data being structured." – matheorem Feb 04 '21 at 08:23
  • 1
    @matheorem, for your second question see update – user21 Feb 04 '21 at 08:29
  • 1
    @matheorem, here is a guess, If you are querying f outside it will have to generate an extrapolation value and it has to generate the Message. That might be the cost. If f2 is queried outside then you have the expense of the finding that the value is outside the domain plus the evaluation of f to get the value. – user21 Feb 04 '21 at 08:32
  • 2
    @matheorem, I have added this example to the documentation. I hope you do not mind. – user21 Feb 04 '21 at 08:33
  • I do not mind, of couse :) Do you mean that PeriodicInterpolation does not support rectangular region? I actually need to interpolate on a parallelpiped region. I am thinking how to pull points outside region back by periodic condition. Do you have any good solution already exists in Mathematica? – matheorem Feb 04 '21 at 09:40
  • About the timing. How to explain the ContourPlot of f2 is even faster than f? – matheorem Feb 04 '21 at 09:42
  • ElementMeshInterpolation does not (can not in general) support PeriodicInterpolation. I don't know about the timing. I would have to take a closer look. Maybe FindGeometricTansform is useful. – user21 Feb 04 '21 at 10:12
  • I have a suggestion. I think If we have explicitly set ExtrapolationHandler, then "outside the range " warning message is redundent and should be removed internally, then we won't have to suppress the message which may cause performance issue – matheorem Feb 04 '21 at 13:22
  • @matheorem, I'll file this as a suggestion. I can not do this immediately. Thanks. To switch if off now you can use `"ExtrapolationHandler" -> {..., "WarningMessage"->False} – user21 Feb 05 '21 at 09:38
  • When I do this: {AbsoluteTiming[ ContourPlot[f[x, y], {x, 0, 4 \[Pi]}, {y, 0, 4 \[Pi]}]], AbsoluteTiming[ ContourPlot[f2[x, y], {x, 0, 4 \[Pi]}, {y, 0, 4 \[Pi]}]], AbsoluteTiming[ ContourPlot[f3[x, y], {x, 0, 4 \[Pi]}, {y, 0, 4 \[Pi]}]]} I do not see any difference between f2 and f3. So the warning message may not be as expensive as I thought it was. – user21 Feb 05 '21 at 09:51
  • You are right. I did timing again, it seems fine now. Maybe I mixed up something previously. "WarningMessage"->False is great, thank you so much – matheorem Feb 08 '21 at 05:19
2

Since currently ElementMeshInterpolation does not support PeriodicInterpolation and Interpolation only support PeriodicInterpolation on rectangular grid. Apart from user21's workaround, I developed a workaround for arbitrary parallel or parallelipiped grid periodic interpolation.

The idea is naive, just to pull back points outside region by base vectors. Below is helper function.

pullBack2Dcom=Compile[{x1,x2,y1,y2,x,y},Mod[{(-x2 y+x y2)/(-x2 y1+x1 y2),(x1 y-x y1)/(-x2 y1+x1 y2)},1].{{x1,y1},{x2,y2}}];
pullBack3Dcom=Compile[{x1,y1,z1,x2,y2,z2,x3,y3,z3,x,y,z},Mod[{(x3 y2 z-x2 y3 z-x3 y z2+x y3 z2+x2 y z3-x y2 z3)/(x3 y2 z1-x2 y3 z1-x3 y1 z2+x1 y3 z2+x2 y1 z3-x1 y2 z3),(x3 y1 z-x1 y3 z-x3 y z1+x y3 z1+x1 y z3-x y1 z3)/(-x3 y2 z1+x2 y3 z1+x3 y1 z2-x1 y3 z2-x2 y1 z3+x1 y2 z3),(x2 y1 z-x1 y2 z-x2 y z1+x y2 z1+x1 y z2-x y1 z2)/(x3 y2 z1-x2 y3 z1-x3 y1 z2+x1 y3 z2+x2 y1 z3-x1 y2 z3)},1].{{x1,y1,z1},{x2,y2,z2},{x3,y3,z3}}];
pullBack2D[{{x1_,y1_},{x2_,y2_}},{x_,y_}]:=pullBack2Dcom[x1,x2,y1,y2,x,y];
pullBack3D[{{x1_,y1_,z1_},{x2_,y2_,z2_},{x3_,y3_,z3_}},{x_,y_,z_}]:=pullBack3Dcom[x1,y1,z1,x2,y2,z2,x3,y3,z3,x,y,z];

The expressions above seems complicated, but they are just solution of LinearSolve plus using Mod function.

Now I prepare a parallel grid data set which has periodic boundary condition.

data=N@Flatten[Table[Append[i{1,0}+j*{1,1},Sin[Total[i{1,0}+j*{1,1}]*2*\[Pi]]],{i,0,1.,1/100},{j,0,1.,1/100}],1];
ListContourPlot[data,AspectRatio->Automatic]

which gives

enter image description here

and then do mesh interpolation like below

mesh=ToElementMesh[data[[;;,1;;2]]];
f=ElementMeshInterpolation[{mesh},data[[;;,-1]]];
ContourPlot[f[x,y],{x,y}\[Element]ConvexHullMesh[data[[;;,1;;2]]],AspectRatio->Automatic]

gives

enter image description here

which is good.

Now we can use pullBack2D to generate a periodic function using base vector bvecs

bvecs = {{1, 0}, {1, 1}}
g[x_?NumericQ, y_?NumericQ] := f @@ pullBack2D[bvecs, {x, y}]

plot it using

ContourPlot[g[x, y], {x, 0, 2}, {y, 0, 2}, AspectRatio -> Automatic]

we get

enter image description here

matheorem
  • 17,132
  • 8
  • 45
  • 115
  • You should be able to use a technique like the one here if you have the basis vectors of your "fundamental parallelogram". – J. M.'s missing motivation Feb 04 '21 at 13:15
  • @J.M. Thank you for the link. I see you use LinearSolve and that is exactly what I use except that I use the explict symbolic solution of LinearSolve to use Compile. I found Compile is much faster :) – matheorem Feb 04 '21 at 13:19