7
$\begingroup$

As part of a new subject I'm starting at school, we are required to use Mathematica instead of the more basic CAS calculators. I am currently running the V11.2 Student Edition of Mathematica.

However, after using it for almost a month, I have noticed that it performs significantly slower than my CAS calculator, especially on integrals. I have just tried multiple times to plot two integrals on the same graph using the Plot function but it freezed almost indefinitely (you could still click on it, but the CPU stays around 72% unless it is forced to quit).

The integral I was trying to plot was fairly simple, the CAS can plot it under 2 seconds. I think there must be something wrong, as I've seen much more complicated things being calculated on Mathematica.

Does anyone know how to fix this? I tried using it without the notebook interface, however I need to plot graphs.

f := 68000
m := 2340
r := 68
a[k_, t_] := f/(m + k - r*t) - 10
v[k_, t_] := Integrate[a[k, p], {p, 0, t}]
d[k_] := Integrate[v[k, p], {p, 0, k/r}]
r1 := 200
a1[k_, t_] := f/(m + k - r1*t) - 10
v1[k_, t_] := Integrate[a1[k, p], {p, 0, t}]
d1[k_] := Integrate[v1[k, p], {p, 0, k/r1}]
Plot[{d[x], d1[x]}, {x, 0, 10}]
$\endgroup$
  • $\begingroup$ Mathematica tries to check convergence and therefore needs to know more about your parameter k. $\endgroup$ – Ulrich Neumann Feb 20 '18 at 12:27
  • $\begingroup$ @UlrichNeumann Is that what's causing the slow plotting? I've been currently running Mariusz's solution for 5 minutes but it doesn't seem to spitting out a graph. $\endgroup$ – user55405 Feb 20 '18 at 12:44
  • 1
    $\begingroup$ @WeavingBird1917, that and also the use of := without Evaluate. Basically the integration is done anew for each point when building the plot, I think. $\endgroup$ – Kiro Feb 20 '18 at 12:46
  • $\begingroup$ @Kiro Thank you. Integrating for each point point must take a really long time. I've been trying one of the solutions posted, but it doesn't seem to be spitting a graph any time soon. I will try looking up some examples on Evaluate. $\endgroup$ – user55405 Feb 20 '18 at 12:48
8
$\begingroup$

Here is my take on this. Key points are the use of Evaluate, to make sure that Integrate is called only once and not every time d is called, and the use of Assumptions, where I took the liberty of assuming that k is real.

I hope I didn't mix up the limits.

{f, m, r} = {68000, 2340, 68};
a[k_, t_] := f/(m + k - r t) - 10
d[k_] := Evaluate[
   Integrate[a[k, t], {p, 0, k/r}, {t, 0, p}, 
    Assumptions -> k \[Element] Reals]];
Plot[d[x], {x, 0, 10}]

enter image description here

For the other one,

r1 = 200;
a1[k_, t_] := f/(m + k - r1 t) - 10
d1[k_] := 
  Evaluate[Integrate[a1[k, t], {p, 0, k/r1}, {t, 0, p}, 
    Assumptions -> k \[Element] Reals]];
Plot[d1[x], {x, 0, 10}]

enter image description here

| improve this answer | |
$\endgroup$
  • 5
    $\begingroup$ Why do you even need := delayed assignment if your right-hand part is Evaluated? $\endgroup$ – Ruslan Feb 20 '18 at 16:27
  • $\begingroup$ @Ruslan Good point, the delayed assignment is not doing anything and we might just as well use =. Also, due to Evaluate one should take care that k has not been given any values to get the expected output. $\endgroup$ – Kiro Feb 20 '18 at 20:53
  • 1
    $\begingroup$ If you want to be super safe, you should protect t and p, too: Block[{k, p, t}, d[k_] = Integrate[a[k, t], {p, 0, k/r}, {t, 0, p}, Assumptions -> k \[Element] Reals]; ] $\endgroup$ – Michael E2 Feb 20 '18 at 21:36
7
$\begingroup$

Try:

$Version
(* "11.2.0 for Microsoft Windows (64-bit) (September 11, 2017)" *)

ClearAll["Global`*"]; Remove["Global`*"];(* Clears All variables *)

f = 68000;
m = 2340;
r = 68;
a[k_?NumericQ, t_?NumericQ] := f/(m + k - r*t) - 10
v[k_?NumericQ, t_?NumericQ] := NIntegrate[a[k, p], {p, 0, t}, Method -> {Automatic, "SymbolicProcessing" -> 0}]; 
d[k_?NumericQ] := NIntegrate[v[k, p], {p, 0, k/r}, Method -> {Automatic, "SymbolicProcessing" -> 0}];
r1 := 200
a1[k_?NumericQ, t_?NumericQ] := f/(m + k - r1*t) - 10
v1[k_?NumericQ, t_?NumericQ] := NIntegrate[a1[k, p], {p, 0, t}, Method -> {Automatic, "SymbolicProcessing" -> 0}]
d1[k_?NumericQ] := NIntegrate[v1[k, p], {p, 0, k/r1}, Method -> {Automatic, "SymbolicProcessing" -> 0}]

Plot[{d[x], d1[x]}, {x, 0, 10}] // AbsoluteTiming

enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ @WeavingBird1917.In my 3 years old laptop, about 3.7 seconds. $\endgroup$ – Mariusz Iwaniuk Feb 20 '18 at 12:54
  • $\begingroup$ Thank you! I opened it in a new notebook and it plotted almost instantaneously! I marked Kiro's as the answer because he goes through some points that would be helpful for newcomers, however this method works perfectly too. $\endgroup$ – user55405 Feb 20 '18 at 12:54
5
$\begingroup$

Aside from necessary Assumptions mentioned in another answers, your problem is that you're abusing delayed assignment — the := operator. It results in the right-hand side being evaluated every time you call your function or use your variable — unless the right-hand side has been wrapped with Evaluate function. I.e., Integrate functions are re-evaluating the integrals each time you call your v, d, v1 and d1 functions.

The proper way, after adding the necessary Assumptions for the integrals is to replace your := with = — at least for the calls to Integrate, although in your specific case you don't need delayed assignment at all, so you could simply replace all of the operators with immediate assignments.

Now, if you know that your variable $k$ in the whole computation satisfies $k\in\mathbb R$, then you can wrap the computation in Assuming function or just set $Assumptions variable to your assumption at the beginning. (Don't forget to reset the variable later to the default value of True when you do unrelated calculations.)

After taking all this into account, your code could look like this:

f = 68000;
m = 2340;
r = 68;
r1 = 200;
a[k_, t_] = f/(m + k - r*t) - 10;
a1[k_, t_] = f/(m + k - r1*t) - 10;
Assuming[Element[k, Reals],
 v[k_, t_] = Integrate[a[k, p], {p, 0, t}];
 d[k_] = Integrate[v[k, p], {p, 0, k/r}];
 v1[k_, t_] = Integrate[a1[k, p], {p, 0, t}];
 d1[k_] = Integrate[v1[k, p], {p, 0, k/r1}];
 Plot[{d[x], d1[x]}, {x, 0, 10}]
]

output of the code above

More on := and = assignments see in Immediate and Delayed Definitions tutorial.

| improve this answer | |
$\endgroup$
2
$\begingroup$

You can solve your problem more directly

Clear[f,m,r]
Integrate[f/(m + k - r*t) - 10, {t, 0, k/r}, {p, 0, t},Assumptions ->{Element[{m, k}, Reals], k > 0, m > 0}]
(* -((k (f + 5 k) + f (k + m) Log[m/(k + m)])/r^2) *)
Plot[% /. {f -> 68000, m -> 2340, r -> 68}, {k, 0, 10}]

enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ Shouldn't it be Integrate[f/(m + k - r*t) - 10, {p, 0, k/r}, {t, 0, p}]? $\endgroup$ – Kiro Feb 20 '18 at 12:43
  • 1
    $\begingroup$ ups my answer was given to fast, thank you $\endgroup$ – Ulrich Neumann Feb 20 '18 at 13:09

Your Answer

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