CaRMtl/rene/zirkel/expression/Romberg.java

101 lines
2.7 KiB
Java

/*
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz
This file is part of C.a.R. software.
C.a.R. is a free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 3 of the License.
C.a.R. is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package rene.zirkel.expression;
import rene.zirkel.construction.ConstructionException;
import rene.zirkel.objects.Evaluator;
public class Romberg {
/**
* Summiere f(x),f(x+h),...,f(x+n*h)
*/
private static double sumUp(final Evaluator F, final double x,
final double h, final int n) throws ConstructionException {
double sum = F.evaluateF(x);
for (int i = 1; i <= n; i++) {
sum = sum + F.evaluateF(x + i * h);
}
return sum;
}
/**
* Romberg-Verfahren.
*
* @param a
* ,b = Intervall-Grenzen
* @param F
* = Funktion, die integriert wird
* @param nstart
* = Anzahl der ersten Unterteilungen
* @param eps
* = Relative Genauigkeit zum Abbruch
* @param maxiter
* = Maximale Iterationen
* @return Integral oder RuntimeException
*/
static public double compute(final Evaluator F, final double a,
final double b, final int nstart, final double eps,
final int maxiter) throws ConstructionException {
// Ergebnisse der Trapezregel mit Schrittweite h/2^i
final double t[] = new double[maxiter];
int n = nstart;
// Anfangsschrittweite
double h = (b - a) / n;
// Berechne Trapezregel dazu und d[0]
double tlast = t[0] = (F.evaluateF(a) + F.evaluateF(b) + 2 * sumUp(F, a
+ h, h, n - 2))
* h / 2;
// Bisheriges Ergebnis festhalten
double old = t[0];
// Halbiere Schrittweite bis Genauigkeit erreicht
for (int i = 1; i < maxiter; i++) { // Halbiere Schrittweite:
h = h / 2;
n = n * 2;
// Berechne Trapezregel (unter Verwendung des
// letzten Ergebnisses:
t[i] = tlast / 2 + sumUp(F, a + h, 2 * h, n / 2 - 1) * h;
tlast = t[i];
// Update der t[i]:
double q = 4;
for (int j = i - 1; j >= 0; j--) {
t[j] = t[j + 1] + (t[j + 1] - t[j]) / (q - 1);
q = q * 4;
}
// Abbruch-Kriterium
final double res = t[0];
if (Math.abs((res - old) / res) < eps)
return res;
old = res;
}
// Bei ?berschreiten der Interationsgrenze:
return tlast;
}
}