1
$\begingroup$

I'm trying to create a custom version of NIntegrate, called MyNIntegrate, with custom option behavior. In particular, I'd like the following criteria to be met:

  • Default values for AccuracyGoal and PrecisionGoal are both 10.
  • Unless WorkingPrecision is set explicitly when calling MyNIntegrate, this option automatically takes the value of three times the maximum of AccuracyGoal and PrecisionGoal.
  • Any of the standard options for NIntegrate can be fed into MyNIntegrate explicitly, and are then passed along to NIntegrate.

I've tried implementing this with the standard Options tools, but I don't really know what opts:OptionsPattern[] and OptionValue are doing under the hood, so I'm having trouble.

$\endgroup$

1 Answer 1

3
$\begingroup$

The following seems to do what you want. (You might wanna remove the Print line at some point.)

Clear[MyNIntegrate];
Options[MyNIntegrate] = Options[NIntegrate];
MyNIntegrate[int_, args___] :=
  Block[{ranges, opts},
   opts = Cases[{args}, _Rule];
   ranges = Complement[{args}, opts];
   
   If[FreeQ[opts, AccuracyGoal -> _], opts = Append[opts, AccuracyGoal -> 10]];
   If[FreeQ[opts, PrecisionGoal -> _], opts = Append[opts, PrecisionGoal -> 10]];
   
   If[FreeQ[opts, WorkingPrecision -> _],
    opts = 
     Append[opts, 
      WorkingPrecision -> 3*Max[AccuracyGoal /. opts, PrecisionGoal /. opts]]
    ];

   Print[opts];

   NIntegrate[int, Evaluate[Sequence @@ ranges], Evaluate[opts]]
  ];
MyNIntegrate[1/Sqrt[x + y], {x, 0, 1}, {y, 0, 1}, 
 PrecisionGoal -> 20, 
 Method -> {"GlobalAdaptive", Method -> "ClenshawCurtisRule"}, 
 MaxRecursion -> 20]

(*During evaluation of In[173]:= {PrecisionGoal->20,Method->{GlobalAdaptive,Method->ClenshawCurtisRule},MaxRecursion->20,AccuracyGoal->10,WorkingPrecision->60}*)

(* 1.10456949966230204653590120649568830997449857498155244452310 *)
MyNIntegrate[1/Sqrt[x + y], {x, 0, 1}, {y, 0, 1}, 
 PrecisionGoal -> 12, WorkingPrecision -> MachinePrecision, 
 Method -> {"GlobalAdaptive", Method -> "ClenshawCurtisRule"}, 
 MinRecursion -> 3, MaxRecursion -> 20]

(* During evaluation of In[175]:= {PrecisionGoal->12,WorkingPrecision->MachinePrecision,Method->{GlobalAdaptive,Method->ClenshawCurtisRule},MinRecursion->3,MaxRecursion->20,AccuracyGoal->10} *)

(* 1.10457 *)
```
$\endgroup$
5
  • $\begingroup$ Thanks, this does the trick. $\endgroup$
    – WillG
    Nov 11, 2020 at 21:42
  • $\begingroup$ Can you explain why the Evaluate is necessary in the Evaluate[opts]? I noticed that it doesn't work without this, but I don't understand why. $\endgroup$
    – WillG
    Nov 11, 2020 at 22:31
  • $\begingroup$ "Can you explain why the Evaluate is necessary[...]" -- NIntegrate has the attribute HoldAll. $\endgroup$ Nov 11, 2020 at 23:21
  • $\begingroup$ But why does opts need to be evaluated? It is just a list of options. $\endgroup$
    – WillG
    Nov 12, 2020 at 14:06
  • 1
    $\begingroup$ "But why does opts need to be evaluated? It is just a list of options." -- Because NIntegrate has the attribute HoldAll without Evaluate NIntegrate "sees" a symbol opts, not a list of options. $\endgroup$ Nov 12, 2020 at 14:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.