docs: def differential_pressure_meter_solver(D, rho, mu, k, D2=None, P1=None, P2=None, 
                                         m=None, meter_type=ISO_5167_ORIFICE, 
                                         taps=None):
      r'''Calculates either the mass flow rate, the upstream pressure, the second
      pressure value, or the orifice diameter for a differential
      pressure flow meter based on the geometry of the meter, measured pressures 
      of the meter, and the density, viscosity, and isentropic exponent of the 
      fluid. This solves an equation iteratively to obtain the correct flow rate.
      
      Parameters
      ----------
      D : float
          Upstream internal pipe diameter, [m]
      rho : float
          Density of fluid at `P1`, [kg/m^3]
      mu : float
          Viscosity of fluid at `P1`, [Pa*s]
      k : float
          Isentropic exponent of fluid, [-]
      D2 : float, optional
          Diameter of orifice, or venturi meter orifice, or flow tube orifice,
          or cone meter end diameter, or wedge meter fluid flow height, [m]
      P1 : float, optional
          Static pressure of fluid upstream of differential pressure meter at the
          cross-section of the pressure tap, [Pa]
      P2 : float, optional
          Static pressure of fluid downstream of differential pressure meter or 
          at the prescribed location (varies by type of meter) [Pa]
      m : float, optional
          Mass flow rate of fluid through the flow meter, [kg/s]
      meter_type : str, optional
          One of ('ISO 5167 orifice', 'long radius nozzle', 'ISA 1932 nozzle', 
          'venuri nozzle', 'as cast convergent venturi tube', 
          'machined convergent venturi tube', 
          'rough welded convergent venturi tube', 'cone meter',
          'wedge meter'), [-]
      taps : str, optional
          The orientation of the taps; one of 'corner', 'flange', 'D', or 'D/2';
          applies for orifice meters only, [-]
          
      Returns
      -------
      ans : float
          One of `m`, the mass flow rate of the fluid; `P1`, the pressure 
          upstream of the flow meter; `P2`, the second pressure
          tap's value; and `D2`, the diameter of the measuring device; units
          of respectively, kg/s, Pa, Pa, or m
  
      Notes
      -----
      See the appropriate functions for the documentation for the formulas and
      references used in each method.
      
      The solvers make some assumptions about the range of values answers may be
      in.
      
      Note that the solver for the upstream pressure uses the provided values of
      density, viscosity and isentropic exponent; whereas these values all
      depend on pressure (albeit to a small extent). An outer loop should be
      added with pressure-dependent values calculated in it for maximum accuracy.
      
      It would be possible to solve for the upstream pipe diameter, but there is
      no use for that functionality.
      
      Examples
      --------
      >>> differential_pressure_meter_solver(D=0.07366, D2=0.05, P1=200000.0, 
      ... P2=183000.0, rho=999.1, mu=0.0011, k=1.33, 
      ... meter_type='ISO 5167 orifice', taps='D')
      7.702338035732167
      
      >>> differential_pressure_meter_solver(D=0.07366, m=7.702338, P1=200000.0, 
      ... P2=183000.0, rho=999.1, mu=0.0011, k=1.33, 
      ... meter_type='ISO 5167 orifice', taps='D')
      0.04999999990831885
      '''
      if m is None and None not in (D, D2, P1, P2):
          
          def to_solve(m_D):
              m = m_D*D
              epsilon, C = differential_pressure_meter_C_epsilon(D, D2, m, P1, P2, rho, 
                                                            mu, k, meter_type, 
                                                            taps=taps)
              m_calc = flow_meter_discharge(D=D, Do=D2, P1=P1, P2=P2, rho=rho, 
                                          C=C, expansibility=epsilon)
              err =  m - m_calc
              return err
          # Diameter to mass flow ratio
          m_D_guess = 40
          if rho < 100.0:
              m_D_guess *= 1e-2
          return secant(to_solve, m_D_guess)*D
      elif D2 is None and None not in (D, m, P1, P2):
          def to_solve(D2):
              epsilon, C = differential_pressure_meter_C_epsilon(D, D2, m, P1, P2, rho, 
                                                            mu, k, meter_type, 
                                                            taps=taps)
              m_calc = flow_meter_discharge(D=D, Do=D2, P1=P1, P2=P2, rho=rho, 
                                          C=C, expansibility=epsilon)
              return m - m_calc    
          return brenth(to_solve, D*(1-1E-9), D*5E-3)
      elif P2 is None and None not in (D, D2, m, P1):
          def to_solve(P2):
              epsilon, C = differential_pressure_meter_C_epsilon(D, D2, m, P1, P2, rho, 
                                                            mu, k, meter_type, 
                                                            taps=taps)
              m_calc = flow_meter_discharge(D=D, Do=D2, P1=P1, P2=P2, rho=rho, 
                                          C=C, expansibility=epsilon)
              return m - m_calc    
          return brenth(to_solve, P1*(1-1E-9), P1*0.5)
      elif P1 is None and None not in (D, D2, m, P2):
          def to_solve(P1):
              epsilon, C = differential_pressure_meter_C_epsilon(D, D2, m, P1, P2, rho, 
                                                            mu, k, meter_type, 
                                                            taps=taps)
              m_calc = flow_meter_discharge(D=D, Do=D2, P1=P1, P2=P2, rho=rho, 
                                          C=C, expansibility=epsilon)
              return m - m_calc    
          return brenth(to_solve, P2*(1+1E-9), P2*1.4)
      else:
          raise ValueError('Solver is capable of solving for one of P2, D2, or m only.')