3

I have a problem with my loop. I would like to set nominal diameter as value from nominal_diameters list. For example my calc_diameter=130 so I'd like that nominal_diameter=125. So far in this code I am getting nominal_diameter = 0 .

What should I change in my loop?

import math

print('Welcome in PipeDiameter program. It helps you to choose the right size of pipe for'
      ' sewerage pressure systems.')
flow=round(float(input('Please enter your sewage flow [(m^3)/s]:')),2)
speed_assumed = 1
calc_diameter=round(math.sqrt(((4*flow)/((math.pi)*speed_assumed))*1000),2)
print(str(calc_diameter)+' mm')

nominal_diameters=[90,110,125,160,180,200,225,250,315,355,400,450,500,560,630,710,800]
inner_diameters=[(90-2*5,4),(110-2*6,6),(125-2*7,4),(160-2*9,5),(180-2*10,7),(200-2*11,9),
                 (225-2*13,4),(250-2*14,8),(315-2*18,7),(355-2*21,1),(400-2*23,7),(450-2*26,7),
                 (500-2*29,7),(560-2*33,2),(630-2*37,4),(710-2*42,1),(800-2*47,4)]

nominal_diameter=0
i=0

while nominal_diameters[i]<=calc_diameter<=nominal_diameters[i+1]:
    nominal_diameter=nominal_diameters[i]
    i=i+1
print(nominal_diameter)
5
  • Why if calc_diameter=130 should nominal_diameter=125? And not 160? Or what if calc_diameter=124? Also what about thickness list? Commented Dec 5, 2018 at 6:34
  • do you really need this condition? calc_diameter<=nominal_diameters[i+1]? Commented Dec 5, 2018 at 6:36
  • 1
    The condition fails for the first check 90 <= 130 <= 110 and so the loop is never entered. Could you explain what you are trying to do in the loop? Is the nominal_diameter supposed to be the value in the list that is closest to the calc_diameter? Commented Dec 5, 2018 at 6:36
  • remove the second condition calc_diameter<=nominal_diameters[i+1] you will get the desiered output Commented Dec 5, 2018 at 6:40
  • 1
    @iGian for calc_diameter=130 should nominal_diameter=125, not 160 because it has connection with further calculation. speed_assumed is 1 in my example and this speed is minimum. In further I will calculate a real speed inside the pipe. To do that I need thickness list inner diameter. And as smaller pipe as speed is higher, this is why nominal_diameter should be lower than calc_diameter. You helped without knowing that. Thanks ! Commented Dec 5, 2018 at 16:45

4 Answers 4

1

An alternative to while loop, since appears to be a select the problem:

nominal_diameters=[90,110,125,160,180,200,225,250,315,355,400,450,500,560,630,710,800]

calc_diameter = 130
select_diam = min([(abs(d-calc_diameter), d) for d in nominal_diameters ])[1]

print(select_diam) #=> 125

For calc_diameter = 195 it returns 200.

How it works

By list comprehension it maps the list of nominal_diameters to a list of tuples with this couple of values: the absolute (abs()) difference between the required diameter and the nominal diameter and the nominal diameter itself ((abs(d-calc_diameter), d)).

Then it pick the minimum (min()) tuple on the list, finally from the minimum pick the second element ([1]), which is the nominal diameter.

This is for example the map for calc_diameter = 130:

[(40, 90), (20, 110), (5, 125), (30, 160), (50, 180), (70, 200), (95, 225), (120, 250), (185, 315), (225, 355), (270, 400), (320, 450), (370, 500), (430, 560), (500, 630), (580, 710), (670, 800)]
                      ^^^^^^^^
Sign up to request clarification or add additional context in comments.

1 Comment

This does not work as intended. For calc_diameter=195 you would get 180 and not 200.
1

The problem is that if the condition is not satisfied for the first value the loop is never entered, and hence your nominal diameter will evaluate to 0. You can change your code as below

while True:
        if nominal_diameters[i] <= calc_diameter <= nominal_diameters[i + 1]:
            nominal_diameter = nominal_diameters[i]
            break
        i = i + 1

This should solve the problem

Comments

1

I understand that based on the calc_diameter you what to find what value of nominal_diameters list is the one closest to that. You could do this as follows (an example with calc_diameter=130):

import numpy as np

nominal_diameters=[90,110,125,160,180,200,225,250,315,355,400,450,500,560,630,710,800]
calc_diameter = 130

best_approx = np.argmin([np.abs(d-calc_diameter) for d in nominal_diameters]) # Provides the index in nominal_diameters with value closest to calc_diameter
print(nominal_diameters[best_approx]) # Outputs 125

2 Comments

I am getting error: 'AttributeError: module 'numpy' has no attribute 'argmin'. Do you know what I am doing wrong ?
Weird, numpy definitely has argmin and I tested this code and worked well for me.
1

The problem lies here:

while nominal_diameters[i] <= calc_diameter <= nominal_diameters[i+1]:

Assume that calc_diameter = 300, in that case the statement reads as

while 90 <= 300 <= 110:

Which will fail immediately, leaving you with 0.

You can solve it by doing something like this:

for i in range(len(nominal_diameters)-1):
    if nominal_diameters[i] <= calc_diameter <= nominal_diameters[i+1]:
        nominal_diameter = nominal_diameters[i]
        break
else:
    if calc_diameter < nominal_diameters[0]:
        nominal_diameter = nominal_diameters[0]
    else:
        nominal_diameter = nominal_diameters[-1]

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.