MetPy icon indicating copy to clipboard operation
MetPy copied to clipboard

Dry_Lapse broadcast for multiple input starting temperature

Open gitlinffff opened this issue 6 months ago • 2 comments

What went wrong?

p = np.array([1000., 950., 900., 850., 800., 750., 700., 650., 600., 550., 500., 450., 400., 350., 300., 250., 200., 175., 150., 125., 100., 80., 70., 60., 50., 40., 30., 25., 20.]) T = np.array([15, 20]) dry_lapse(p * units.hPa, T * units.degC)

ValueError: operands could not be broadcast together with shapes (2,) (29,)

It should have treated T as multiple starting temperature and return dry adiabatic profile for each starting temperature, instead of requiring p and T to have the same shape. It is also necessary to add a pytest for multiple starting temperature.

Operating System

MacOS

Version

v1.7

Python Version

3.13.3

Code to Reproduce

p = np.array([1000., 950., 900., 850., 800., 750., 700., 650., 600.,
     550., 500., 450., 400., 350., 300., 250., 200.,
     175., 150., 125., 100., 80., 70., 60., 50.,
     40., 30., 25., 20.])
T = np.array([15, 20])
dry_lapse(p * units.hPa, T * units.degC)

Errors, Traceback, and Logs

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[3], line 6
      1 p = np.array([1000., 950., 900., 850., 800., 750., 700., 650., 600.,
      2      550., 500., 450., 400., 350., 300., 250., 200.,
      3      175., 150., 125., 100., 80., 70., 60., 50.,
      4      40., 30., 25., 20.])
      5 T = np.array([15, 20])
----> 6 calc.dry_lapse(p * units.hPa, T * units.degC)

File ~/git_repos/MetPy/src/metpy/xarray.py:1330, in preprocess_and_wrap.<locals>.decorator.<locals>.wrapper(*args, **kwargs)
   1327     _mutate_arguments(bound_args, units.Quantity, lambda arg, _: arg.m)
   1329 # Evaluate inner calculation
-> 1330 result = func(*bound_args.args, **bound_args.kwargs)
   1332 # Wrap output based on match and match_unit
   1333 if match is None:

File ~/git_repos/MetPy/src/metpy/units.py:337, in check_units.<locals>.dec.<locals>.wrapper(*args, **kwargs)
    334 @functools.wraps(func)
    335 def wrapper(*args, **kwargs):
    336     _check_units_inner_helper(func, sig, defaults, dims, *args, **kwargs)
--> 337     return func(*args, **kwargs)

File ~/git_repos/MetPy/src/metpy/calc/thermo.py:513, in dry_lapse(pressure, temperature, reference_pressure, vertical_dim)
    511 if reference_pressure is None:
    512     reference_pressure = pressure[0]
--> 513 return temperature * (pressure / reference_pressure)**mpconsts.kappa

File ~/miniforge3/envs/metpy_dev/lib/python3.13/site-packages/pint/facets/plain/quantity.py:1018, in PlainQuantity.__mul__(self, other)
   1017 def __mul__(self, other):
-> 1018     return self._mul_div(other, operator.mul)

File ~/miniforge3/envs/metpy_dev/lib/python3.13/site-packages/pint/facets/plain/quantity.py:101, in check_implemented.<locals>.wrapped(self, *args, **kwargs)
     99 elif isinstance(other, list) and other and isinstance(other[0], type(self)):
    100     return NotImplemented
--> 101 return f(self, *args, **kwargs)

File ~/miniforge3/envs/metpy_dev/lib/python3.13/site-packages/pint/facets/plain/quantity.py:75, in ireduce_dimensions.<locals>.wrapped(self, *args, **kwargs)
     74 def wrapped(self, *args, **kwargs):
---> 75     result = f(self, *args, **kwargs)
     76     try:
     77         if result._REGISTRY.autoconvert_to_preferred:

File ~/miniforge3/envs/metpy_dev/lib/python3.13/site-packages/pint/facets/plain/quantity.py:1006, in PlainQuantity._mul_div(self, other, magnitude_op, units_op)
   1003 elif no_offset_units_other == len(other._units) == 1:
   1004     other = other.to_root_units()
-> 1006 magnitude = magnitude_op(new_self._magnitude, other._magnitude)
   1007 units = units_op(new_self._units, other._units)
   1009 return self.__class__(magnitude, units)

ValueError: operands could not be broadcast together with shapes (2,) (29,)

gitlinffff avatar Jun 24 '25 23:06 gitlinffff

Does this work?

dry_lapse(p.reshape(-1, np.newaxis) * units.hPa, T.reshape(np.newaxis, -1) * units.degC)

DWesl avatar Jun 25 '25 22:06 DWesl

I agree with @DWesl 's code above, if you pass in arrays so that the math would work following NumPy's broadcasting rules you should get the results you expect.

dopplershift avatar Jun 27 '25 17:06 dopplershift