u/Environmental_Pen866

Help with program acknowledging a solved variable

Help with program acknowledging a solved variable

https://preview.redd.it/4qgj2df4101h1.png?width=1920&format=png&auto=webp&s=9d23e74a08b63576bc640bac13f72e22f45e5400

Hey everyone, this is my first coding project and I'm having trouble with my program not recognising that it has solved for I. I was thinking that adding: if name == "I" and symbol in subs: continue. would stop it from looping but it doesn't.

Any suggestions would be appreciated.

# Beam deflection calculator
# Calculates maximum beam deflection under a uniformly distributed load
# Uses the beam deflection formula


from sympy import Symbol, solve, pprint
import math


# Allows safe math input
safe_dict = {"__builtins__": None}
safe_dict.update(vars(math))


# To track which axis is solved for if I is calculated
axis = None 


# Symbol definitions
w = Symbol('w')
L = Symbol('L')
E = Symbol('E')
I = Symbol('I')
δ_max = Symbol('d') 


# Beam deflection formula (simply-supported, uniform load):
expr = (5*w*L**4)/(384*E*I) 


# Introduction to the program
print("\nWelcome to the Beam Deflection Calculator")
print("\nThis program calculates the maximum beam deflection under a uniformly distributed load")


# Equation setup
equation = δ_max - expr 
print('\nBeam Deflection Equation:')
pprint(equation)
print('\nVariables: w, L, E, I, d(δ)')


# Define allowed variables for user input
valid_symbols = {
    'w' : w,
    'L' : L,
    'E' : E,
    'I' : I,
    'd' : δ_max
}


# Define SI units for each variable
units = {
    'w' : 'N/m',
    'L' : 'm',
    'E' : 'Pa',
    'I' : 'm^4',
    'd' : 'm'
}


# Unit conversions to standard factors for each variable
conversion_factors = {
    'w' : {'N/m': 1, 'kN/m': 1e3, 'N/mm': 1e3, 'kN/mm': 1e6},
    'L' : {'m': 1, 'mm': 1e-3, 'cm': 1e-2, 'km': 1e3},
    'E' : {'Pa': 1, 'MPa': 1e6, 'GPa': 1e9, 'N/m^2': 1, 'N/mm^2': 1e6, 'N/km^2': 1e-6},
    'I' : {'m^4':1, 'mm^4': 1e-12, 'cm^4': 1e-8, 'km^4': 1e12},
    'd' : {'m': 1, 'mm': 1e-3, 'cm': 1e-2, 'km': 1e3}
}


# Prompt for variables & ensure a valid user input
while True:
    solve_for = input('\nWhich variable would you like to solve for? (w, L, E, I, d): ').strip()
    print("\nEnter values in ANY of the prompted units; results are always reported in SI units (N/m, m, Pa, m^4, m).\n")
    if solve_for in valid_symbols:
        break
    print('Unable to solve for variable')
    print('Try: w, L, E, I, d')


# Solve for symbols
var = valid_symbols[solve_for]


# Confirm choice
print(f'\nYou selected to solve for {solve_for}.')
print('Enter values for the remaining variables.\n')


subs = {}


# Get user to input values for all other variables
for name, symbol in valid_symbols.items():
    if name != solve_for:
        allowed_units = list(conversion_factors[name].keys())


        # If user requests to solve for I:
        if name == "I":
            while True: 
                use_rect = input(
                    "\nDo you want to calculate I for a rectangular section? (y/n): "
                ).strip().lower()
                if use_rect not in {"y", "n"}:
                    print("Please answer 'y' or 'n'.")
                    continue 
                if use_rect == "y":
                    while True:
                        axis_try = input("Calculate bending about which axis? (x/y): ").strip().lower()
                        if axis_try not in {"x", "y"}:
                            print ("Axis must be 'x' or 'y'. Try again.")
                            continue
                        axis = axis_try
                        try:
                            base = float(input("Enter base b (width) of rectangle: "))
                            b_unit = input("Unit for b (m, mm, cm, km): ").strip()
                            height = float(input('Enter height h of rectangle: '))
                            h_unit = input("unit for h (m, mm, cm, km): ").strip()
                        except Exception:
                            print("[!] Invalid numeric value for b or h.")
                            continue


                        conv_b = conversion_factors['L'].get(b_unit, None)
                        conv_h = conversion_factors['L'].get(h_unit, None)
                        if conv_b is None or conv_h is None:
                            print('[!] Invalid unit for b or h. Allowed: m, mm, cm, km')
                            continue
                        b_si = base * conv_b
                        h_si = height * conv_h


                        if axis == "x": 
                            I_si = (1/12) * b_si * h_si**3
                            pretty_I = (f"Ix = (1/12) * {b_si} * {h_si}^3 = {I_si} m^4")
                        else:
                            I_si = (1/12) * h_si * b_si**3
                            pretty_I = (f'Iy = (1/12) * {h_si} * {b_si}^3 = {I_si} m^4')
                        print("\nSection dimensions (SI):")
                        print(f" base = {b_si} m, height = {h_si} m")
                        print(pretty_I)
                        subs[symbol] = I_si
                        break # User input for I finished
                    if name == "I" and symbol in subs:
                        continue
                else:
                    # When user want's to input predetermined value for I, continue to manual entry below
                    break    
        
        # For manual entry of all other values 
        while True:
            print(f'\nEnter value for {name}. Allowed units: {', '.join(allowed_units)}')
            try:
                value_input = input(f'Value for {name}: ').strip().lower()
                value_input = value_input.replace('x', '*').replace('^', '**')


                try:
                    value = float(eval(value_input, safe_dict))
                except:
                    print(' [!] Invalid logarithm form. Try: e-n or *10^-n or x 10^n')
                    continue    


                unit = input(f'Unit for {name}: ').strip()
               
                if unit not in conversion_factors[name]:
                    print(f' [!] Invalid unit. Allowed: {', '.join(allowed_units)}')
                    continue


                value_si = value * conversion_factors[name][unit]
                if name in ['w', 'L', 'E', 'I', 'd'] and value_si <= 0:
                    print(" [!] Value must be positive.")
                    continue
                print(f' {name}: {value} {unit} → {value_si} {units[name]} (SI)')
                subs[symbol] = value_si
                break
            except Exception:
                print(' [!] Invalid input. Please enter a numeric value.')
                


# Solve for the variable first without substitution
solution = solve(equation, var)


# Substitute the known values and evaluate
solution = [sol.subs(subs).evalf() for sol in solution]


# keep only real, positive solutions
real_positive = [sol for sol in solution if sol.is_real and sol > 0]


print("\n=== RESULT ===")
if real_positive:
    result = real_positive[0]
    print(f'\n{solve_for} = {result} {units[solve_for]}')
    if axis:
        print(f"deflection calculated for bending about the {axis}-axis.")
else:
    print(' [!] No valid physical solution found.')
    exit()


if L in subs:
    beam_length = subs[L]
else:
    beam_length = result


max_deflection_location = beam_length / 2


print(f'\nx_max = {max_deflection_location} m (midpoint of beam)')


print('\n--- Calculation finished. Thank you for using the Beam Deflection Calculator! ---')
reddit.com
u/Environmental_Pen866 — 10 days ago