How to converge on a value for an iterative function

Question:

`A iterative function I wrote is unable to converge on a value, I believe the function is not updating the last calculated value at the beginning of each new loop and thus not converging and instead calculating only one value each time.

Ive tried the function below, the issue is that for any f input I put it will calculate a subsequent f0 value but it wont repeat the loop with the new value and instead just return f0.`

import numpy as np

Q = 62549.5 #gpm
L = 52800 #ft
a = (100 / 1.10) #Right side of energy balance 
Vis = 1.537*10**(-5)
e = 0.0015 # in

f = 0.008
ep = 0.00001
list = np.linspace(0.005, 1, 5)


def friction(f):
  convergence = True
  while convergence:
    D = ((f*L*(Q**2))/(32.15*a))**(1/5)
    A = (3.14*(D/12)**2)/4 #ft^2
    v = (Q/448.831)/A #ft/s
    Re = (v*(D/12))/Vis
    f0 = 0.25/(np.log10(e/(3.7*D) + 5.74/(Re**(9/10))))**2

    convergence = abs((f0-f)/f0) < ep
    f = f0
    break
  return f0

for f in list:
   print(friction(f))
Asked By: ChristianA.

||

Answers:

Although I’m not 100% on whether the values It spit out for me are correct as I don’t know much about calculating friction as i assume this is doing, this worked when I tried it(working meaning it gave different values when input was changed but same values for repeated inputs). you could try removing the break. I’m assuming that you may be breaking out of the loop before a convergence is met. you can add an if statement and set convergence to false when its met. or if you prefer to use break, you can use it instead in the if statement. Here’s how I ran it, if I got the idea wrong I apologize.

import numpy as np

Q = 62549.5  # gpm
L = 52800  # ft
a = (100 / 1.10)  # Right side of energy balance
Vis = 1.537 * 10 ** (-5)
e = 0.0015  # in

f = 0.008
ep = 0.00001


def friction(f):
    convergence = True
    while convergence:
        D = ((f * L * (Q ** 2)) / (32.15 * a)) ** (1 / 5)
        A = (3.14 * (D / 12) ** 2) / 4  # ft^2
        v = (Q / 448.831) / A  # ft/s
        Re = (v * (D / 12)) / Vis
        f0 = 0.25 / (np.log10(e / (3.7 * D) + 5.74 / (Re ** (9 / 10)))) ** 2

        f = f0
        # I used an if statement so that when satisfied 
        # it sets convergence to false and loop ends
        if abs((f0 - f) / f0) < ep:
            convergence = False # This could be set to break, to
                                # immediately break loop if preferred
    return f0


if __name__ == '__main__':
    inPut = 0.008 # This is how I was changed input variable
    print(friction(inPut))
Answered By: WBarber
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.