velocity profile of laminar flow in a pipe for a university project I want to compute the laminar flow velocity at 7 points in a cross-section of a pipe. Later we want to use this data for a flow animation.

Inputs of my function are the diameter and length of the pipe, the viscosity of the fluid, the pressure difference and the average velocity.

For the calculation I only need the pressure difference or the average velocity. So I have to set either the pressure difference or the average velocity to False.

Do you have any idea how I can improve the code?

import numpy as np


def flow(diameter, viscosity, len_pipe, dp, v_average):
    radius = diameter / 2.
    x = np.linspace(-radius, radius, 7)

    if not v_average and dp:
        dpdx = dp / float(len_pipe)
        v = radius**2 / (4*viscosity) * (-dpdx) * (1-(x/radius)**2)
        vmax = max(v)
        v_average = vmax / 2
    elif not dp and v_average:
        vmax = 2 * v_average
        dpdx = -4 * vmax * viscosity / radius**2
        dp = dpdx * len_pipe
        v = radius**2 / (4*viscosity) * (-dpdx) * (1-(x/radius)**2)

    return dp, v_average, x, v, vmax
I think this is a good starting point, but some better code organization will help you in the long run

I would first summarize a few main problems I see:


Unclear input parameters
Ambiguous path execution
The most important part is hard-coded
Too many output parameters
Repetition of code (i.e. violation of DRY)


All of this basically boils down to code organization.  Rather than just showing you a different solution, I think its best to explain the issues:


The usage of db and v_average is such that it isn't immediately clear how to use your method.  It's best if a user can look at your method and see exactly how it is supposed to be called.  Some docstrings would help.  Also, since these parameters are optional, they should be named parameters, not positional ones: def flow(diameter, viscosity, len_pipe, dp=False, v_average=False).  Otherwise they have to pass in False to dp in order to use v_average, and that is less than ideal.
Your code will break if someone passes False in both for dp and v_average.  You want a nice guard up top: if not dp and not v_average: raise ValueError('You must provide either dp or v_average)  This makes your code self-documenting, and avoids bugs.  Also, you should have a guard to return an error if both have a value.  That is just as much a user mistake, and will have an ambiguous return value if the two passed in values don't agree.
The post important thing in your code is the locations where you want the flow velocity.  This is the entire point of your function: to calculate flow velocity at some points.  However, you have the points hard-coded.  Sure, you want it at 7 points right now, but what if your needs change?  You have to re-write your function.  That's no good.  Just let x be an input parameter, and let the user provide it.
You are returning too many things as output parameters.  This is basically a violation of separation of concerns.  All you should really be returning is v, which is easier if the user passes in x.  You don't have to return dp or v_average.  Effectively, your function is doing 5 things: calculating some x values of interest, calculating dp if v_average is provided, calculating v_average if dp is provided, calculating v, and calculating vmax.  You need a function that does less.


Also, while I don't know much about laminar flows, the statistician/physicist in me says that you are using a strange definition of average velocity: v_average = vmax / 2.  I'm going to assume for now that v_average doesn't refer to an actual statistical average, but that it has a different definition in your particular use-case.

Small Changes

So what do you do about this?  Personally, I think you should just separate this into two separate functions: flow_from_dp and flow_from_v_average.  Pass in x, lose the extraneous input parameter, and return only v.  If the user wants to figure out vmax, then make a separate function: calculate_vmax.  Similarly, I would make helper functions that can calculate dp from v_average and vice-versa.  Having more functions that do less is actually a good thing in this case.  Each function will have a clear calling sequence and return only one thing.  That is exactly what you want.  I'll leave actually making that change as an exercise for the reader :)

Big Changes

Another option would be to make this code OOP.  I would envision a pipe class that has a diameter and length.  You could also have a fluid class that has a viscosity and dp or v_average.  It would then automatically calculate the one given the other.  Your flow method would then become bound to one of the classes, or it could be a method that simply accepts a pipe and a fluid and calculates the velocity at a given set of points.  I'm not going into a crazy amount of detail here simply because I don't know whether or not that might be a useful suggestion for you, as that largely depends on your level of familiarity with OOP.  If you are interested, I would be happy to give an example of what an OOP solution would look like.