Do you also get the warning message which says that the Integrate failed to converge to prescribed accuracy ...?
Yes. NIntegrate[]
checks an error estimate. If the error estimate is larger than the error prescribed by PrecisionGoal
and AccuracyGoal
, then NIntegrate[]
complains. This will happen often if you set MaxRecursion
to zero. If you set PrecisionGoal -> -1, AccuracyGoal -> -1
, then it doesn't complain about convergence (well, hardly ever).
What do you mean by....
Sorry, that was my mistake. I was in a hurry and didn't have time to check the documentation. Ignore "interior points." For some reason, "Points"
often does not mean the actual number of points used in an integration rule. It's a parameter that affects the number of points. (For instance, the Romberg step needs
$2n-1$ points, and the "Points"
parameter is
$n$.)
If you're trying to have simple demonstrations for students, one of the difficulties to face up to is that generally speaking, Mathematica is set up to give high-quality results, using sophisticated techniques under the hood. To get it to do the naive thing usually means setting a bunch of options that have a chance of confusing the student.
Of course, your demo code is simple and clear. I suppose you're just checking it against NIntegrate[]
. But there you still run into a conflict between its sophisticated approach and the desired naive approach.
You probably don't need the following, but I have the code sitting around. It makes calling Nintegrate[]
simple, but the user has to remember to define myTrapRule
below. It's relatively easy to define any interpolatory integration rule in Mathematica. The internal data structure used to represent the rule has the following form:
NIntegrate`GeneralRule[{abscissas, integration_weights, error_weights}]
You can add a rule to NIntegrate
's repertory by extending the definition of NIntegrate`InitializeIntegrationRule[]
as follows (the unexplained arguments allow for greater sophistication, which is not needed here):
Options[myTrapRule] = {"Points" -> 2};
myTrapRule /: NIntegrate`InitializeIntegrationRule[
myTrapRule, nfs_, ranges_, ruleOpts_, allOpts_] :=
Module[{abscissas, weights, nPoints},
nPoints = OptionValue[myTrapRule, ruleOpts, "Points"];
abscissas = Subdivide[0, 1, nPoints - 1];
weights = ConstantArray[1, nPoints]/(nPoints - 1);
weights[[{1, -1}]] /= 2;
NIntegrate`GeneralRule[{abscissas, weights, 0*weights}]
];
Then:
NIntegrate[x^2, {x, 0, 3}, Method -> {myTrapRule, "Points" -> 5}]
(* 9.28125 *)
NIntegrate[x^2, {x, 0, 3}, Method -> {myTrapRule, "Points" -> 6}]
(* 9.18 *)
The error weights are set to zero on purpose. There will be no recursion because the rule reports an error of zero on the first try. NIntegrate[]
does not care if you lie to it. You can redefine the meaning of "Points"
as you see fit. The abscissas are obtained by subdividing the unit interval [0, 1]. NIntegrate[]
rescales an integral to be over [0, 1], so you do not need to worry about other intervals. (Infinite intervals usually get special handling that does not apply to integrals for which myTrapRule
is an appropriate rule.)