-1
$\begingroup$

I intend to run a NIntegrate inside a Do loop. At first I import the integrand as a txt file and then number it using loop number because I need them after exiting the loop. But when I run the code it can't specify the integrand. I can't write all my code here, but a toy example can be

Do[
f[i] = x^2 + 3 y;
 ans = NIntegrate[f[i], {x, 0, 10}];
 Print[ans]
 , {i, 1, 2}]

(*NIntegrate[f[i],{x,0,10}]
NIntegrate[f[i],{x,0,10}]
*)

As you can see the printed results show that the code failed to specify the f[1] and f[2] correctly. How can deal with this problem?

Addendum

this is the simple scheme of my code

enter image description here

Note that the fCorrHFE[mp] is a function itself and I will plot it in the next step.

$\endgroup$
5
  • 1
    $\begingroup$ Please paste minimal code. The Do loops will run but the loop variables won't be advancing?? Do[expr, {i, imax}] should be the syntax, i think? $\endgroup$
    – Syed
    Oct 17 '21 at 12:05
  • $\begingroup$ I know, but as I said this is just a scheme to understand my code $\endgroup$
    – Wisdom
    Oct 17 '21 at 12:10
  • $\begingroup$ Did you run the code in my preliminary answer, where does it not work for you? Assuming that your integrand is now an expression and that it has limits supplied to it, what is the error now? When you import a file, does it have one integrand per file? $\endgroup$
    – Syed
    Oct 17 '21 at 12:13
  • $\begingroup$ Sorry but I don't understand how your code can solve the problem? Note that the answer of numerical integration is a function itself and I will supply the remained limit in plot command $\endgroup$
    – Wisdom
    Oct 17 '21 at 12:16
  • $\begingroup$ I don't understand how the NIntegrate will give you a function but then I don't understand a lot. $\endgroup$
    – Syed
    Oct 17 '21 at 12:20
2
$\begingroup$

This is a comment about how to create an MWE from the addendum in this specific case. Currently the addendum cannot be executed because it depends on unavailable files.

One can mimic reading a group of files with Association. One should only imitate a minimal number of files. Arguably it's 2 or 4 in this case (test distinct values for mp and w/omega). It's important that the mock expressions for the file contents have the same variables as in the real case. I would say you can use a simpler expression; problems with NIntegrate converging should be asked as a separate question, where the actual integrand will be needed.

In the loop, I did nothing to fix the inherent problems with the code. I did merge the nested Do loops. The role of Import is performed by the association readFile. I treated the integrand as a temporary variable, but integrand[mp] can be used if desired.

readFile = Association@Flatten@Table[ (* imports fake data *)
     StringTemplate["gE_m=`1`-w=`2`.txt"][mp, w] ->
      StringTemplate["`1` x+y^`2`"][mp, w],
     {mp, 2}, {w, 2}];

Do[
 filename = StringTemplate["gE_m=`1`-w=`2`.txt"][mp, w];
 integrand = ToExpression@readFile[filename];
 fCorrHFE[mp] = NIntegrate[integrand, {x, 0, 20}];,
 {w, 2}, {mp, 2}]

The above does not address any of the problems in the OP:

  • NIntegrate evaluates on an expression that is not numeric when x equals a number.
  • fCorrHFE[mp] does not depend on w, so that all the values for w = 1 are overwritten in the next iteration of the Do[] loop.
  • fCorrHFE[mp] represents an expression that depends on y, every time fCorrHFE[mp] is evaluated, NIntegrate will give errors unless y has a numeric value at the time.

This addresses those problems:

Block[{NIntegrate},
 Do[
  filename = StringTemplate["gE_m=`1`-w=`2`.txt"][mp, w];
  integrand = ToExpression@readFile[filename];
  fCorrHFE[mp, w, y_?NumericQ] = NIntegrate[integrand, {x, 0, 20}],
  {w, 2}, {mp, 2}]
 ]

Suspending execution while constructing code to be evaluated later is one of the functions of Block[]. The use of = instead of := in the definition fCorrHFE allows integrand to be evaluated (since the attributes of NIntegrate are blocked as well as its execution).

$\endgroup$
1
  • $\begingroup$ Thank you very much for your detailed explanation and useful points, However it wasn't the exact answer of my question. $\endgroup$
    – Wisdom
    Oct 18 '21 at 19:36
3
$\begingroup$
  • If the integrand is a string, use ToExpression.
  • If the integrand has x and y as variables, supply the limits.
    Clear[x, y, i, f]
    Do[
     Echo[i];
     f[i] = ToExpression["x^2+3y"];
     Echo[f[i]];
     ans = NIntegrate[f[i], {x, 0, 10}, {y, 0, 10}];
     Print[ans], {i, 1, 2}
    ]
$\endgroup$
1
  • $\begingroup$ Please see my addendum $\endgroup$
    – Wisdom
    Oct 17 '21 at 11:54
2
$\begingroup$

As you can see the printed results show that the code failed to specify the f[1] and f[2] correctly. How can deal with this problem?

I will interpret "correctly" to mean that you see f[i] and not either x^2 + y or f[1] etc. Since NIntegrate has the attribute HoldAll, you need to either evaluate f[i] or inject i.

Evaluate:

ans = NIntegrate[Evaluate@f[i], {x, 0, 10}]

Mathematica graphics

Inject:

ans = With[{i = i}, NIntegrate[f[i], {x, 0, 10}]]

Mathematica graphics

Comment: This seems an XY Problem in which the real problem Y is kept from us in favor of problem X, because either the OP thinks problem Y is too complex and problem X captures the essence of Y or the OP is certain that solving problem X will allow them to solve Y. But there are aspects of X that are inherently confusing. The expression f[i] is not really a function but indexed data; moreover, it's the same for every index i. The addendum mentions that ans/fCorrHFE[mp] is itself a "function," although to experienced Mathematica users, it does not appear programmatically to be a function. Presumably it is an expression that depends on uninitialized parameters. In that case, ans might be defined something like the following. The exact usage is unclear in the OP, but the following avoids wasting time and a lot of error messages by not pointlessly evaluating NIntegrate. Be sure to Clear[ans] before the Do loop:

ans[i] = 
  Function[{y1, y2}, NIntegrate[#, {x, 0, 10}, {y, y1, y2}]] &[f[i]];

(Note that the evaluation approach is problematic in this case. The integrand is too deep inside nested HoldAll functions for Evaluate to work. Injection with With[{i = i},...] causes the arguments of Function to be rewritten {y1$, y2$}, which works as long as the expressions represented by f[1] etc. do not depend on y1 or y2.)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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