enum DifferenceFormula
{
Euler,
- UpwindEuler
+ UpwindEuler,
+ FourthOrder
};
* its scalar product with @p{b}.
*
* The derivative is computed numerically, using one of the provided
- * difference formulas.
+ * difference formulas (see @p{set_formula} for available
+ * schemes). Experimenting with @p{h} and the difference scheme may be
+ * necessary to obtain sufficient results.
*
* @author Guido Kanschat, 2000
*/
* Choose the difference formula.
* This is set to the default in
* the constructor.
+ *
+ * Formulas implemented right now
+ * are first order backward Euler
+ * (@p{UpwindEuler}), second order
+ * symmetric Euler (@p{Euler}) and
+ * a symmetric fourth order formula
+ * (@p{FourthOrder}).
*/
void set_formula (DifferenceFormula formula = Euler);
formula = form;
}
-
+//TODO: Discussion on an efficient implementation of Point additions.
template <int dim>
double
return (f.value(p+incr, component)-f.value(p-incr, component))/(2*h);
case UpwindEuler:
return (f.value(p, component)-f.value(p-incr, component))/h;
+ case FourthOrder:
+ return (-f.value(p+2*incr, component) + 8*f.value(p+incr, component)
+ -8*f.value(p-incr, component) + f.value(p-2*incr, component))/(12*h);
default:
Assert(false, ExcInvalidFormula());
}
values[i] = (values[i]-e2[i])/h;
break;
}
+ case FourthOrder:
+ {
+ vector<Point<dim> > p_p(n);
+ vector<Point<dim> > p_pp(n);
+ vector<Point<dim> > p_m(n);
+ vector<Point<dim> > p_mm(n);
+ vector<double> e_p(n);
+ vector<double> e_pp(n);
+ vector<double> e_m(n);
+ for (unsigned int i=0;i<n;++i)
+ {
+ p_p[i] = points[i]+incr;
+ p_pp[i] = p_p[i]+incr;
+ p_m[i] = points[i]-incr;
+ p_mm[i] = p_m[i]-incr;
+ }
+ f.value_list(p_mm, values, component);
+ f.value_list(p_pp, e_pp, component);
+ f.value_list(p_p, e_p, component);
+ f.value_list(p_m, e_m, component);
+
+ for (unsigned int i=0;i<n;++i)
+ {
+ values[i] = (values[i]-p_pp[i]+8*(p_p[i]-p_m[i]))/(12*h);
+ }
+ break;
+ }
+
default:
Assert(false, ExcInvalidFormula());
}