Message Boards Message Boards

How do I repeat/loop multiple functions that are related?

Posted 9 years ago
POSTED BY: Thai Kee Gan
12 Replies

Mathematica has a short tutorial entitled "Arbitrary-Precision Numbers." You can find it by searching for "tutorial/ArbitraryPrecisionNumbers" in Help/Wolfram Documentation or by typing SetPrecision, highlighting it, pressing F1, then find the link for the tutorial at the bottom of the page.

POSTED BY: Charles Elliott
Posted 9 years ago

Thanks again for your help and your advice, Dr. Charles Elliott (correct me if I'm wrong). I will try to digest everything. Hopefully.

POSTED BY: Thai Kee Gan
Attachments:
POSTED BY: Charles Elliott
Posted 9 years ago

Hello again, sorry for the trouble. I've tried NDSolve method to search for "z" instead of ParametricNDSolveValue So here's what I done but still there's some error.

prog := Module[{Twater = 300., Tnew = 0, Cwater, Dwater, Ewater, 
    ClassicalRungeKuttaCoefficients, f, x, y, z = 60, point, ans, 
    tol = 0.001, iters = 0, iterLim = 100, prevTnew = 10^5, 
    plotList = {}}, $MinPrecison = 50;
   Cwater = 
    QuantityMagnitude[
     ThermodynamicData["Water", 
      "ThermalConductivity", {"Temperature" -> 
        Quantity[Twater, "Kelvins"]}]];
   ans = "Twinkle, twinkle, little star,
             How I wonder what you are.
             Up above the world so high,
             Like a diamond in the sky.
             Twinkle, twinkle, little star,
             How I wonder what you are!";

   While[(Abs[prevTnew - Tnew] > tol) && (iters++ < iterLim), 
    Dwater = (5 Cwater)/Pi;
    Ewater = Dwater^3 + 2*Cwater;

    While[
      (Abs[point] < 100) && (iters++ < iterLim),

      ClassicalRungeKuttaCoefficients[4, prec_] :=
       With[{amat = {{1/2}, {0, 1/2}, {0, 0, 1}}, 
         bvec = {1/6, 1/3, 1/3, 1/6}, cvec = {1/2, 1/2, 1}}, 
        N[{amat, bvec, cvec}, prec]];

      f = 
       NDSolve[{SetPrecision[
          Derivative[1][y][x] == 
           Piecewise[{{(y[x] + x^3 + 3 z - 120*Ewater), 
              0 <= x <= 1}, {(y[x] + x^2 + 2 z), 
              1 <= x <= 2}, {(y[x] + x + z), 2 <= x <= 3}}], 40], 
         y[0] == 0}, y, {x, 0., 3.}, 
        Method -> {"ExplicitRungeKutta", "DifferenceOrder" -> 4, 
          "Coefficients" -> ClassicalRungeKuttaCoefficients}, 
        StartingStepSize -> 1/100];

      point = y[1] /. f[[1]];

      z++

      ]

     Print[point];



    prevTnew = Tnew;

    Tnew = 170 + 1.89*z;

    Cwater = 
     QuantityMagnitude[
      ThermodynamicData["Water", 
       "ThermalConductivity", {"Temperature" -> 
         Quantity[Tnew, "Kelvins"]}]];

    (*Note Tnew here!*)
    Print["Twater: ", Twater, " Tnew: ", Tnew];];

   (*End while*)

   ans = {"Tnew: ", Tnew, "Cwater: ", Cwater, "Dwater: ", Dwater, 
     "Ewater: ", Ewater};
   Print["The answer is:\n", ans];];

What I tried to do is to have "While Loop" inside a "While Loop" and instead of FindRoot, I use ReplaceAll, Here's the plan,

The inner loop is to find the value of "z" so that the "point" is 100, and the increment of "z" is 1 each time. After it reach the correct value of "z", the the command will continue to look for Tnew, and repeat again.

But the problem is

 point = y[1] /. f[[1]];

does not work properly in the While loop. I can do it outside of While loop but not inside. So, i'm stuck here

POSTED BY: Thai Kee Gan
POSTED BY: Charles Elliott
Posted 9 years ago

Hello Charles, thank you for your advice. You are correct about my background, that i have not been exposed to numerical analysis as much as I supposed to have. In the future, I will definitely take up PhD program if there is a chance.

POSTED BY: Thai Kee Gan
Posted 9 years ago

OMG THANK YOU VERY MUCH. It totally works. I will not be able to get it correct by myself. The codes posted here is an alternate code for my research. Sorry I cant disclose it here. Here's the explanation. I'm an engineering master student working on heat transfer. In this case, it's about fluid. For the code, I would need to find the value of "z" so that "y=100". For a given condition, the "Twater" changes and the thermal conductivity of water. Then, "z" will be replace into Tnew equation. If Twater=Tnew, then that is the temperature that we want. At first, I was thinking to try to iterate with If,Do,While loop, with step size 0.001...., but that will take forever. After some trial, Tnew will actually converge, so I wanted to replace Twater with Tnew. This equation is some kind of temperature loop.

I will study the code given and learn more about the commands.

BTW,

Cwater = QuantityMagnitude[
   ThermodynamicData["Water", 
    "ThermalConductivity", {"Temperature" -> 
      Quantity[Twater, "Kelvins"]}]];

Is there any reason to have Cwater outside of the While loop? Well I tried putting it into the While loop and the loop just stop after 2 iterations. It will be helpful for me to understand this.

POSTED BY: Thai Kee Gan

I made the algorithm converge to an answer; I have no idea if it is correct. Here are the changes I made:

I replaced the statement Twater = Tnew, with Cwater = QuantityMagnitude[ ThermodynamicData["Water", "ThermalConductivity", {"Temperature" -> Quantity[Tnew, "Kelvins"]}]]; <-- note the Tnew here. I added the variable prevTnew, initialized it to 10^5, and set it to Tnew just before Tnew is computed. I changed the completion test to (Abs[prevTnew - Tnew] > tol) && (iters++ < iterLim). Also, please note I created the variable plotList, and initialized it to plotList = {}. Then after you compute point, I added AppendTo[plotList, point]. Later, you could put in Print[ListPlot[plotList]] if the reason you compute point is to plot it. I don't understand the 100 in point. Here is the new routine:

prog := Module[{Twater = 300., Tnew = 0, Cwater, Dwater, Ewater, 
    ClassicalRungeKuttaCoefficients, f, x, y, point, ans, tol = 0.001,
     iters = 0, iterLim = 100, prevTnew = 10^5, plotList = {}},
   $MinPrecison = 50; 
   Cwater = 
    QuantityMagnitude[
     ThermodynamicData["Water", 
      "ThermalConductivity", {"Temperature" -> 
        Quantity[Twater, "Kelvins"]}]];
   ans = "Twinkle, twinkle, little star,
         How I wonder what you are.
         Up above the world so high,
         Like a diamond in the sky.
         Twinkle, twinkle, little star,
         How I wonder what you are!";
   While[(Abs[prevTnew - Tnew] > tol) && (iters++ < iterLim), 
    Dwater = (5 Cwater)/Pi;
    Ewater = Dwater^3 + 2*Cwater;
    ClassicalRungeKuttaCoefficients[4, prec_] := 
     With[{amat = {{1/2}, {0, 1/2}, {0, 0, 1}}, 
       bvec = {1/6, 1/3, 1/3, 1/6}, cvec = {1/2, 1/2, 1}}, 
      N[{amat, bvec, cvec}, prec]];
    f = ParametricNDSolveValue[{SetPrecision[
        Derivative[1][y][x] == 
         Piecewise[{{(y[x] + x^3 + 3 z - 120*Ewater), 
            0 <= x <= 1}, {(y[x] + x^2 + 2 z), 
            1 <= x <= 2}, {(y[x] + x + z), 2 <= x <= 3}}], 40], 
       y[0] == 0}, y[3.], {x, 0., 3.}, z, 
      Method -> {"ExplicitRungeKutta", "DifferenceOrder" -> 4, 
        "Coefficients" -> ClassicalRungeKuttaCoefficients}, 
      StartingStepSize -> 1/10];
    point = {z /. FindRoot[f[z] == 100., {z, 1}, Evaluated -> False], 
      100.};
    AppendTo[plotList, point];
    Print[point];
    FindRoot[f[z] == 100., {z, 1}, Evaluated -> False];
    prevTnew = Tnew;
    Tnew = 
     170 + 1.89*z /. 
      FindRoot[f[z] == 100., {z, 1}, Evaluated -> False];
    Cwater = 
     QuantityMagnitude[
      ThermodynamicData["Water", 
       "ThermalConductivity", {"Temperature" -> 
         Quantity[Tnew, "Kelvins"]}]]; (* Note Tnew here! *)
    Print["Twater: ", Twater, " Tnew: ", Tnew];
    ];(*End while*)
   ans = {"Tnew: ", Tnew, "Cwater: ", Cwater, "Dwater: ", Dwater, 
     "Ewater: ", Ewater};
   Print["The answer is:\n", ans];
   ];
POSTED BY: Charles Elliott
Posted 9 years ago

Hold on..... I suppose when we replace Twater with Tnew, then

While[(Abs[Twater - Tnew] > tol) && (iters++ < iterLim),

will not hold True anymore, that is why the iteration only run once.... So, how do I change it?, or I can just use the conventional method, which is much more "messy"?

n = 5; While[0 < n - 1 < 9, Print[n]; n = n - 0.5]
POSTED BY: Thai Kee Gan
Posted 9 years ago

Hello again, I've tried the code you provided. The output of the code is

prog
{67.9545,100.}
Twater: 300 Tnew: 298.434
The answer is:
Twinkle, twinkle, little star.

The answer for Tnew is the answer for the first loop. The exact answer can be achieve at about 10 to 15 loops and Tnew = 295.565 I think I'm not fully understand how While[] loop works. From the documentation, While[test,body] is to run a number of tests on the body until it no longer holds true right? But the loop only run once....

I'm sorry I need to ask the questions here because this is the only place I can learn Mathematica

From the code give

While[(Abs[Twater - Tnew] > tol) && (iters++ < iterLim),

Does it means that the "test" of while is to check whether Twater-Tnew is more than tol (0.001), if it is yes, the continue the iteration by replace Twater with Tnew from the code at the end right?

 Twater = Tnew

Or there's something I missed?

POSTED BY: Thai Kee Gan

The code below is the general method, but I am not sure it achieves the correct answer. Start it by "Shift+Enter" or "Keypad Enter" on the cell containing prog. You debug it by putting in print statements until you find the error.

prog := Module[{Twater = 300, Tnew = 0, Cwater, Dwater, Ewater, 
    ClassicalRungeKuttaCoefficients, f, x, y, point, ans, tol = 0.001,
     iters = 0, iterLim = 100},
   Cwater = 
    QuantityMagnitude[
     ThermodynamicData["Water", 
      "ThermalConductivity", {"Temperature" -> 
        Quantity[Twater, "Kelvins"]}]];
   ans = "Twinkle, twinkle, little star,
     How I wonder what you are.
     Up above the world so high,
     Like a diamond in the sky.
     Twinkle, twinkle, little star,
     How I wonder what you are!";
   While[(Abs[Twater - Tnew] > tol) && (iters++ < iterLim),
    Dwater = (5 Cwater)/Pi;
    Ewater = Dwater^3 + 2*Cwater;
    ClassicalRungeKuttaCoefficients[4, prec_] := 
     With[{amat = {{1/2}, {0, 1/2}, {0, 0, 1}}, 
       bvec = {1/6, 1/3, 1/3, 1/6}, cvec = {1/2, 1/2, 1}}, 
      N[{amat, bvec, cvec}, prec]];
    f = ParametricNDSolveValue[{Derivative[1][y][x] == 
        Piecewise[{{(y[x] + x^3 + 3 z - 120*Ewater), 
           0 <= x <= 1}, {(y[x] + x^2 + 2 z), 
           1 <= x <= 2}, {(y[x] + x + z), 2 <= x <= 3}}], y[0] == 0}, 
      y[3.], {x, 0., 3.}, z, 
      Method -> {"ExplicitRungeKutta", "DifferenceOrder" -> 4, 
        "Coefficients" -> ClassicalRungeKuttaCoefficients}, 
      StartingStepSize -> 1/10];
    point = {z /. FindRoot[f[z] == 100., {z, 1}, Evaluated -> False], 
      100.};
    Print[point];
    FindRoot[f[z] == 100., {z, 1}, Evaluated -> False];
    Tnew = 
     170 + 1.89*z /. 
      FindRoot[f[z] == 100., {z, 1}, Evaluated -> False];
    Print["Twater: ", Twater, " Tnew: ", Tnew];
    Twater = Tnew;
    ];  (* End while *)
   Print["The answer is:\n", ans];
   ];

prog

POSTED BY: Charles Elliott
Posted 9 years ago

I was wondering if Module[] has something to do with it. It's just that the examples given in the documentation was just for simple tasks. I'm not in my Uni's lab right now (since the software was bought by Uni), but I'll get to it as soon as I can and let you know the result. Thank you very much.

POSTED BY: Thai Kee Gan
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract