Endliche Differenzableitung auf extrapolierten Daten

Oct 14 2020

Ich habe eine (in Wirklichkeit komplexe) Funktion auf einem Gitter, die ungefähr an den Grenzen des Gitters verschwindet und die ich auf ein größeres Gitter projizieren möchte. Beispiel:

fx = Interpolation[
   Transpose[{Range[-2.5, 2.5, 0.01], 
     Exp[-x^2] /. x -> Range[-2.5, 2.5, 0.01]}], 
   "ExtrapolationHandler" -> {0 &, "WarningMessage" -> False}];
fx2 = Transpose[{Range[-3, 3, 0.01], 
    fx[p] /. p -> Range[-3, 3, 0.01]}];

Dann möchte ich die Ableitung dieser Funktion nehmen:

dfx2 = Transpose[{fx2[[All, 1]], NDSolve`FiniteDifferenceDerivative[Derivative[1], fx2[[All, 1]], 
     fx2[[All, 2]], "DifferenceOrder" -> 5]}];

Wenn ich dann diese Ableitung ListPlot, erhalte ich diese hässlichen Punkte an der Grenze des ersten Gitters:

Ich weiß, dass sie wegen der Diskontinuität an der Grenze des ersten Gitters kommen, aber ich muss sie loswerden. Da dieses Problem in einem viel komplexeren Code auftritt, kann ich einige Dinge nicht ändern:

  1. Ich kann die Reihenfolge der Operationen nicht ändern (neues Gitter kommt vor Ableitung).
  2. Ich kenne die neue Gittergröße nicht und auch nicht die alte Gittergröße (ich weiß vorher nicht, an welchen Positionen diese hässlichen Punkte auftreten)

Ich habe zwei Ideen, wie ich das beheben kann:

  1. Finden Sie einen Weg, wie Mathematica die Funktion so extrapoliert, dass sie sich ungefähr wie die ursprüngliche Funktion verhält (die ich auch nicht kenne), ohne den plötzlichen Sprung auf Null zu vermeiden. Ich weiß jedoch, dass es sich wie A Exp[(x-b)^2/c]an den Grenzen verhält .

  2. Identifizieren Sie diese hässlichen Punkte, nachdem sie aufgetreten sind, und ersetzen Sie sie durch Punkte, die die Funktion reibungslos machen.

Gibt es einen besseren dritten Weg? Und wenn nicht, welchen Weg würden Sie wählen und wie würden Sie ihn umsetzen?

Antworten

3 SjoerdSmit Oct 13 2020 at 23:16

Folgendes können Sie tun: Sie können die Ableitung von interpolieren fxund dann integrieren. Die Ableitung von fxverhält sich außerhalb des Funktionsbereichs gut:

Plot[fx'[x], {x, -3, 3}]

Anstatt die Funktion zu interpolieren und zu differenzieren, können Sie die Ableitung interpolieren und integrieren:

fx2 = Derivative[-1] @ Interpolation[
   Transpose[{Range[-3, 3, 0.01], fx'[Range[-3, 3, 0.01]]}]
];
Plot[{fx2[x], fx2'[x]}, {x, -3, 3}]

Beachten Sie, dass Sie bei der Integration möglicherweise konstante Offsets berücksichtigen müssen.

Aktualisieren

Es sieht so aus, als ob hier eine Methode erforderlich ist, um die Interpolationsfunktion außerhalb des Datenbereichs reibungslos auf Null zu bringen. Hier ist ein Beispiel, wie Sie das tun können:

smoothenToZero[x_, nf_NearestFunction, lambda : _ : 1] := With[{
    nearestXY = First@nf[x, 1]
 },
   nearestXY[[2]] * Exp[-Divide[Subtract[nearestXY[[1]], x], lambda]^2]
];
data = Table[{x, Exp[-x^2]}, {x, -3, 3, 0.01}];
nf = Nearest[data[[All, 1]] -> data];
int = Interpolation[data,
  "ExtrapolationHandler" -> {
    smoothenToZero[#, nf, 1] &,
    "WarningMessage" -> False
   }
];
LogPlot[int[x], {x, -5, 5}]

Wie Sie sehen, ist die Funktion jetzt beim Übergang von der Interpolation zur Extrapolation zumindest kontinuierlich. Möglicherweise müssen Sie am Übergangsausdruck basteln (vielleicht finden Sie einen, der auch gut zu den Ableitungen passt), aber ich hoffe, dies hilft, Fortschritte zu erzielen.