Getting error “Can only apply 'exp' function to dimensionless quantities”, Not sure how to fix this

本秂侑毒 提交于 2020-05-17 08:46:06

问题


I have been working on converting some MatLab code over to python for one of my professors (not an assignment just working on putting together some stuff) and I am stuck on this one part.

When I run the code I am getting UnitTypeError: "Can only apply 'exp' function to dimensionless quantities", all of the methods I have tried to fix this won't work. I imagine the error is caused by the linspace command but am not sure. Any help with this would be great.

here is the line

IM0 = ((2*h*c**2)/(l**5))/(np.exp(h*c/( h*c/(k*T1*l)))-1)

with the constants being from astropy

h = const.h;
c = const.c;
k = const.k_B;
l = np.linspace(0, 1.5e-6, 1500);
T1 = 3750

回答1:


The astropy constants are instances of classes. Try extracting the "value" for each before using them as an argument to np.exp():

import astropy.constants as const
import numpy as np

h = const.h.value
c = const.c.value
k = const.k_B.value
l = np.linspace(0, 1.5e-6, 1500);
T1 = 3750
IM0 = ((2*h*c**2)/(l**5))/(np.exp(h*c/( h*c/(k*T1*l)))-1)

However please note there are numerical problems with IM0. The denominator is zero over all l.




回答2:


The accepted answer is fine and works so far as you're confident that the bare values you're using are in the correct dimensions. But in general using .value and throwing away the units information can be potentially dangerous--using Quantities with units ensures that all your calculations are being done with compatible units.

Let's look at just the exponent in your exponential, which normally should be a dimensionless quantity.

First note that all the constants you're using from Astropy have units:

>>> from astropy.constants import h, c, k_B                                     
>>> h                                                                           
<<class 'astropy.constants.codata2018.CODATA2018'> name='Planck constant' value=6.62607015e-34 uncertainty=0.0 unit='J s' reference='CODATA 2018'>
>>> c                                                                           
<<class 'astropy.constants.codata2018.CODATA2018'> name='Speed of light in vacuum' value=299792458.0 uncertainty=0.0 unit='m / s' reference='CODATA 2018'>
>>> k_B                                                                         
<<class 'astropy.constants.codata2018.CODATA2018'> name='Boltzmann constant' value=1.380649e-23 uncertainty=0.0 unit='J / K' reference='CODATA 2018'>

You then declared some unitless values and mixed them in with those:

>>> T1 = 3750
>>> l = np.linspace(0, 1.5e-6, 1500)
>>> h*c/(h*c/(k_B*T1*l))                                                        
/home/embray/.virtualenvs/astropy/lib/python3.6/site-packages/astropy/units/quantity.py:481: RuntimeWarning: divide by zero encountered in true_divide
  result = super().__array_ufunc__(function, method, *arrays, **kwargs)
<Quantity [0.00000000e+00, 5.18088768e-29, 1.03617754e-28, ...,
           7.75578885e-26, 7.76096974e-26, 7.76615063e-26] J / K>

Giving a result in joules per kelvin, from k_B which needs to be canceled out with some values in the correct unit. I'm guessing T1 is supposed to be temperature in Kelvin (I'm not sure about l but let's say it's a thermodynamic beta in J-1 though you should double-check whatever units this value is supposed to be in).

So what you probably want to do is declare these values with appropriate units (as an aside, you can avoid the annoying divide-by-zero by defining some epsilon and using that as the start of your range):

>>> from astropy import units as u
>>> eps = np.finfo(float).eps
>>> T1 = 3750 * u.K                                                             
>>> l = np.linspace(eps, 1.5e-6, 1500) * (u.J**-1)

Now your exponent is properly a dimensionless quantity:

>>> h*c/(h*c/(k_B*T1*l))                                                        
<Quantity [1.14962123e-35, 5.18088882e-29, 1.03617765e-28, ...,
           7.75578885e-26, 7.76096974e-26, 7.76615063e-26]>
>>> np.exp(h*c/(h*c/(k_B*T1*l)))                                                
<Quantity [1., 1., 1., ..., 1., 1., 1.]>

(In this case the dimensionless values were all so close to zero that the exponents round to 1--if this is not correct then you'll want to check some of my assumptions about your units).

In any case, this is how the library is intended to be used, and the error you're getting is a deliberate safecheck against your assumptions.

Update: I saw in your other question that you gave some more context to your problem, in particular specifying that l are wavelengths in meters (this was my first guess but I wasn't sure based on the equation you gave).

Actually you can avoid directly using h and c in your Plank equation by taking advantage of equivalencies. Here you can define l as wavelengths in meters:

>>> l = np.linspace(eps, 1.5e-6, 1500) * u.m

and convert this directly to spectral energy:

>>> E = l.to(u.J, equivalencies=u.spectral())                                   
>>> E                                                                           
<Quantity [8.94615682e-10, 1.98512112e-16, 9.92560670e-17, ...,
           1.32606651e-19, 1.32518128e-19, 1.32429724e-19] J>

Then write the exponent in your Plank's law equation like:

>>> np.exp(E / (k_B * T1))                                                      
/home/embray/.virtualenvs/astropy/lib/python3.6/site-packages/astropy/units/quantity.py:481: RuntimeWarning: overflow encountered in exp
  result = super().__array_ufunc__(function, method, *arrays, **kwargs)
<Quantity [        inf,         inf,         inf, ..., 12.95190431,
           12.92977839, 12.90771972]>

(here it gives some infinities near low wavelengths, but you can avoid this by clipping to a larger lower bound).



来源:https://stackoverflow.com/questions/61489942/getting-error-can-only-apply-exp-function-to-dimensionless-quantities-not-s

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!