chore: 添加虚拟环境到仓库
- 添加 backend_service/venv 虚拟环境 - 包含所有Python依赖包 - 注意:虚拟环境约393MB,包含12655个文件
This commit is contained in:
@@ -0,0 +1,453 @@
|
||||
# isort:skip_file
|
||||
"""
|
||||
Dimensional analysis and unit systems.
|
||||
|
||||
This module defines dimension/unit systems and physical quantities. It is
|
||||
based on a group-theoretical construction where dimensions are represented as
|
||||
vectors (coefficients being the exponents), and units are defined as a dimension
|
||||
to which we added a scale.
|
||||
|
||||
Quantities are built from a factor and a unit, and are the basic objects that
|
||||
one will use when doing computations.
|
||||
|
||||
All objects except systems and prefixes can be used in SymPy expressions.
|
||||
Note that as part of a CAS, various objects do not combine automatically
|
||||
under operations.
|
||||
|
||||
Details about the implementation can be found in the documentation, and we
|
||||
will not repeat all the explanations we gave there concerning our approach.
|
||||
Ideas about future developments can be found on the `Github wiki
|
||||
<https://github.com/sympy/sympy/wiki/Unit-systems>`_, and you should consult
|
||||
this page if you are willing to help.
|
||||
|
||||
Useful functions:
|
||||
|
||||
- ``find_unit``: easily lookup pre-defined units.
|
||||
- ``convert_to(expr, newunit)``: converts an expression into the same
|
||||
expression expressed in another unit.
|
||||
|
||||
"""
|
||||
|
||||
from .dimensions import Dimension, DimensionSystem
|
||||
from .unitsystem import UnitSystem
|
||||
from .util import convert_to
|
||||
from .quantities import Quantity
|
||||
|
||||
from .definitions.dimension_definitions import (
|
||||
amount_of_substance, acceleration, action, area,
|
||||
capacitance, charge, conductance, current, energy,
|
||||
force, frequency, impedance, inductance, length,
|
||||
luminous_intensity, magnetic_density,
|
||||
magnetic_flux, mass, momentum, power, pressure, temperature, time,
|
||||
velocity, voltage, volume
|
||||
)
|
||||
|
||||
Unit = Quantity
|
||||
|
||||
speed = velocity
|
||||
luminosity = luminous_intensity
|
||||
magnetic_flux_density = magnetic_density
|
||||
amount = amount_of_substance
|
||||
|
||||
from .prefixes import (
|
||||
# 10-power based:
|
||||
yotta,
|
||||
zetta,
|
||||
exa,
|
||||
peta,
|
||||
tera,
|
||||
giga,
|
||||
mega,
|
||||
kilo,
|
||||
hecto,
|
||||
deca,
|
||||
deci,
|
||||
centi,
|
||||
milli,
|
||||
micro,
|
||||
nano,
|
||||
pico,
|
||||
femto,
|
||||
atto,
|
||||
zepto,
|
||||
yocto,
|
||||
# 2-power based:
|
||||
kibi,
|
||||
mebi,
|
||||
gibi,
|
||||
tebi,
|
||||
pebi,
|
||||
exbi,
|
||||
)
|
||||
|
||||
from .definitions import (
|
||||
percent, percents,
|
||||
permille,
|
||||
rad, radian, radians,
|
||||
deg, degree, degrees,
|
||||
sr, steradian, steradians,
|
||||
mil, angular_mil, angular_mils,
|
||||
m, meter, meters,
|
||||
kg, kilogram, kilograms,
|
||||
s, second, seconds,
|
||||
A, ampere, amperes,
|
||||
K, kelvin, kelvins,
|
||||
mol, mole, moles,
|
||||
cd, candela, candelas,
|
||||
g, gram, grams,
|
||||
mg, milligram, milligrams,
|
||||
ug, microgram, micrograms,
|
||||
t, tonne, metric_ton,
|
||||
newton, newtons, N,
|
||||
joule, joules, J,
|
||||
watt, watts, W,
|
||||
pascal, pascals, Pa, pa,
|
||||
hertz, hz, Hz,
|
||||
coulomb, coulombs, C,
|
||||
volt, volts, v, V,
|
||||
ohm, ohms,
|
||||
siemens, S, mho, mhos,
|
||||
farad, farads, F,
|
||||
henry, henrys, H,
|
||||
tesla, teslas, T,
|
||||
weber, webers, Wb, wb,
|
||||
optical_power, dioptre, D,
|
||||
lux, lx,
|
||||
katal, kat,
|
||||
gray, Gy,
|
||||
becquerel, Bq,
|
||||
km, kilometer, kilometers,
|
||||
dm, decimeter, decimeters,
|
||||
cm, centimeter, centimeters,
|
||||
mm, millimeter, millimeters,
|
||||
um, micrometer, micrometers, micron, microns,
|
||||
nm, nanometer, nanometers,
|
||||
pm, picometer, picometers,
|
||||
ft, foot, feet,
|
||||
inch, inches,
|
||||
yd, yard, yards,
|
||||
mi, mile, miles,
|
||||
nmi, nautical_mile, nautical_miles,
|
||||
angstrom, angstroms,
|
||||
ha, hectare,
|
||||
l, L, liter, liters,
|
||||
dl, dL, deciliter, deciliters,
|
||||
cl, cL, centiliter, centiliters,
|
||||
ml, mL, milliliter, milliliters,
|
||||
ms, millisecond, milliseconds,
|
||||
us, microsecond, microseconds,
|
||||
ns, nanosecond, nanoseconds,
|
||||
ps, picosecond, picoseconds,
|
||||
minute, minutes,
|
||||
h, hour, hours,
|
||||
day, days,
|
||||
anomalistic_year, anomalistic_years,
|
||||
sidereal_year, sidereal_years,
|
||||
tropical_year, tropical_years,
|
||||
common_year, common_years,
|
||||
julian_year, julian_years,
|
||||
draconic_year, draconic_years,
|
||||
gaussian_year, gaussian_years,
|
||||
full_moon_cycle, full_moon_cycles,
|
||||
year, years,
|
||||
G, gravitational_constant,
|
||||
c, speed_of_light,
|
||||
elementary_charge,
|
||||
hbar,
|
||||
planck,
|
||||
eV, electronvolt, electronvolts,
|
||||
avogadro_number,
|
||||
avogadro, avogadro_constant,
|
||||
boltzmann, boltzmann_constant,
|
||||
stefan, stefan_boltzmann_constant,
|
||||
R, molar_gas_constant,
|
||||
faraday_constant,
|
||||
josephson_constant,
|
||||
von_klitzing_constant,
|
||||
Da, dalton, amu, amus, atomic_mass_unit, atomic_mass_constant,
|
||||
me, electron_rest_mass,
|
||||
gee, gees, acceleration_due_to_gravity,
|
||||
u0, magnetic_constant, vacuum_permeability,
|
||||
e0, electric_constant, vacuum_permittivity,
|
||||
Z0, vacuum_impedance,
|
||||
coulomb_constant, electric_force_constant,
|
||||
atmosphere, atmospheres, atm,
|
||||
kPa,
|
||||
bar, bars,
|
||||
pound, pounds,
|
||||
psi,
|
||||
dHg0,
|
||||
mmHg, torr,
|
||||
mmu, mmus, milli_mass_unit,
|
||||
quart, quarts,
|
||||
ly, lightyear, lightyears,
|
||||
au, astronomical_unit, astronomical_units,
|
||||
planck_mass,
|
||||
planck_time,
|
||||
planck_temperature,
|
||||
planck_length,
|
||||
planck_charge,
|
||||
planck_area,
|
||||
planck_volume,
|
||||
planck_momentum,
|
||||
planck_energy,
|
||||
planck_force,
|
||||
planck_power,
|
||||
planck_density,
|
||||
planck_energy_density,
|
||||
planck_intensity,
|
||||
planck_angular_frequency,
|
||||
planck_pressure,
|
||||
planck_current,
|
||||
planck_voltage,
|
||||
planck_impedance,
|
||||
planck_acceleration,
|
||||
bit, bits,
|
||||
byte,
|
||||
kibibyte, kibibytes,
|
||||
mebibyte, mebibytes,
|
||||
gibibyte, gibibytes,
|
||||
tebibyte, tebibytes,
|
||||
pebibyte, pebibytes,
|
||||
exbibyte, exbibytes,
|
||||
)
|
||||
|
||||
from .systems import (
|
||||
mks, mksa, si
|
||||
)
|
||||
|
||||
|
||||
def find_unit(quantity, unit_system="SI"):
|
||||
"""
|
||||
Return a list of matching units or dimension names.
|
||||
|
||||
- If ``quantity`` is a string -- units/dimensions containing the string
|
||||
`quantity`.
|
||||
- If ``quantity`` is a unit or dimension -- units having matching base
|
||||
units or dimensions.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy.physics import units as u
|
||||
>>> u.find_unit('charge')
|
||||
['C', 'coulomb', 'coulombs', 'planck_charge', 'elementary_charge']
|
||||
>>> u.find_unit(u.charge)
|
||||
['C', 'coulomb', 'coulombs', 'planck_charge', 'elementary_charge']
|
||||
>>> u.find_unit("ampere")
|
||||
['ampere', 'amperes']
|
||||
>>> u.find_unit('angstrom')
|
||||
['angstrom', 'angstroms']
|
||||
>>> u.find_unit('volt')
|
||||
['volt', 'volts', 'electronvolt', 'electronvolts', 'planck_voltage']
|
||||
>>> u.find_unit(u.inch**3)[:9]
|
||||
['L', 'l', 'cL', 'cl', 'dL', 'dl', 'mL', 'ml', 'liter']
|
||||
"""
|
||||
unit_system = UnitSystem.get_unit_system(unit_system)
|
||||
|
||||
import sympy.physics.units as u
|
||||
rv = []
|
||||
if isinstance(quantity, str):
|
||||
rv = [i for i in dir(u) if quantity in i and isinstance(getattr(u, i), Quantity)]
|
||||
dim = getattr(u, quantity)
|
||||
if isinstance(dim, Dimension):
|
||||
rv.extend(find_unit(dim))
|
||||
else:
|
||||
for i in sorted(dir(u)):
|
||||
other = getattr(u, i)
|
||||
if not isinstance(other, Quantity):
|
||||
continue
|
||||
if isinstance(quantity, Quantity):
|
||||
if quantity.dimension == other.dimension:
|
||||
rv.append(str(i))
|
||||
elif isinstance(quantity, Dimension):
|
||||
if other.dimension == quantity:
|
||||
rv.append(str(i))
|
||||
elif other.dimension == Dimension(unit_system.get_dimensional_expr(quantity)):
|
||||
rv.append(str(i))
|
||||
return sorted(set(rv), key=lambda x: (len(x), x))
|
||||
|
||||
# NOTE: the old units module had additional variables:
|
||||
# 'density', 'illuminance', 'resistance'.
|
||||
# They were not dimensions, but units (old Unit class).
|
||||
|
||||
__all__ = [
|
||||
'Dimension', 'DimensionSystem',
|
||||
'UnitSystem',
|
||||
'convert_to',
|
||||
'Quantity',
|
||||
|
||||
'amount_of_substance', 'acceleration', 'action', 'area',
|
||||
'capacitance', 'charge', 'conductance', 'current', 'energy',
|
||||
'force', 'frequency', 'impedance', 'inductance', 'length',
|
||||
'luminous_intensity', 'magnetic_density',
|
||||
'magnetic_flux', 'mass', 'momentum', 'power', 'pressure', 'temperature', 'time',
|
||||
'velocity', 'voltage', 'volume',
|
||||
|
||||
'Unit',
|
||||
|
||||
'speed',
|
||||
'luminosity',
|
||||
'magnetic_flux_density',
|
||||
'amount',
|
||||
|
||||
'yotta',
|
||||
'zetta',
|
||||
'exa',
|
||||
'peta',
|
||||
'tera',
|
||||
'giga',
|
||||
'mega',
|
||||
'kilo',
|
||||
'hecto',
|
||||
'deca',
|
||||
'deci',
|
||||
'centi',
|
||||
'milli',
|
||||
'micro',
|
||||
'nano',
|
||||
'pico',
|
||||
'femto',
|
||||
'atto',
|
||||
'zepto',
|
||||
'yocto',
|
||||
|
||||
'kibi',
|
||||
'mebi',
|
||||
'gibi',
|
||||
'tebi',
|
||||
'pebi',
|
||||
'exbi',
|
||||
|
||||
'percent', 'percents',
|
||||
'permille',
|
||||
'rad', 'radian', 'radians',
|
||||
'deg', 'degree', 'degrees',
|
||||
'sr', 'steradian', 'steradians',
|
||||
'mil', 'angular_mil', 'angular_mils',
|
||||
'm', 'meter', 'meters',
|
||||
'kg', 'kilogram', 'kilograms',
|
||||
's', 'second', 'seconds',
|
||||
'A', 'ampere', 'amperes',
|
||||
'K', 'kelvin', 'kelvins',
|
||||
'mol', 'mole', 'moles',
|
||||
'cd', 'candela', 'candelas',
|
||||
'g', 'gram', 'grams',
|
||||
'mg', 'milligram', 'milligrams',
|
||||
'ug', 'microgram', 'micrograms',
|
||||
't', 'tonne', 'metric_ton',
|
||||
'newton', 'newtons', 'N',
|
||||
'joule', 'joules', 'J',
|
||||
'watt', 'watts', 'W',
|
||||
'pascal', 'pascals', 'Pa', 'pa',
|
||||
'hertz', 'hz', 'Hz',
|
||||
'coulomb', 'coulombs', 'C',
|
||||
'volt', 'volts', 'v', 'V',
|
||||
'ohm', 'ohms',
|
||||
'siemens', 'S', 'mho', 'mhos',
|
||||
'farad', 'farads', 'F',
|
||||
'henry', 'henrys', 'H',
|
||||
'tesla', 'teslas', 'T',
|
||||
'weber', 'webers', 'Wb', 'wb',
|
||||
'optical_power', 'dioptre', 'D',
|
||||
'lux', 'lx',
|
||||
'katal', 'kat',
|
||||
'gray', 'Gy',
|
||||
'becquerel', 'Bq',
|
||||
'km', 'kilometer', 'kilometers',
|
||||
'dm', 'decimeter', 'decimeters',
|
||||
'cm', 'centimeter', 'centimeters',
|
||||
'mm', 'millimeter', 'millimeters',
|
||||
'um', 'micrometer', 'micrometers', 'micron', 'microns',
|
||||
'nm', 'nanometer', 'nanometers',
|
||||
'pm', 'picometer', 'picometers',
|
||||
'ft', 'foot', 'feet',
|
||||
'inch', 'inches',
|
||||
'yd', 'yard', 'yards',
|
||||
'mi', 'mile', 'miles',
|
||||
'nmi', 'nautical_mile', 'nautical_miles',
|
||||
'angstrom', 'angstroms',
|
||||
'ha', 'hectare',
|
||||
'l', 'L', 'liter', 'liters',
|
||||
'dl', 'dL', 'deciliter', 'deciliters',
|
||||
'cl', 'cL', 'centiliter', 'centiliters',
|
||||
'ml', 'mL', 'milliliter', 'milliliters',
|
||||
'ms', 'millisecond', 'milliseconds',
|
||||
'us', 'microsecond', 'microseconds',
|
||||
'ns', 'nanosecond', 'nanoseconds',
|
||||
'ps', 'picosecond', 'picoseconds',
|
||||
'minute', 'minutes',
|
||||
'h', 'hour', 'hours',
|
||||
'day', 'days',
|
||||
'anomalistic_year', 'anomalistic_years',
|
||||
'sidereal_year', 'sidereal_years',
|
||||
'tropical_year', 'tropical_years',
|
||||
'common_year', 'common_years',
|
||||
'julian_year', 'julian_years',
|
||||
'draconic_year', 'draconic_years',
|
||||
'gaussian_year', 'gaussian_years',
|
||||
'full_moon_cycle', 'full_moon_cycles',
|
||||
'year', 'years',
|
||||
'G', 'gravitational_constant',
|
||||
'c', 'speed_of_light',
|
||||
'elementary_charge',
|
||||
'hbar',
|
||||
'planck',
|
||||
'eV', 'electronvolt', 'electronvolts',
|
||||
'avogadro_number',
|
||||
'avogadro', 'avogadro_constant',
|
||||
'boltzmann', 'boltzmann_constant',
|
||||
'stefan', 'stefan_boltzmann_constant',
|
||||
'R', 'molar_gas_constant',
|
||||
'faraday_constant',
|
||||
'josephson_constant',
|
||||
'von_klitzing_constant',
|
||||
'Da', 'dalton', 'amu', 'amus', 'atomic_mass_unit', 'atomic_mass_constant',
|
||||
'me', 'electron_rest_mass',
|
||||
'gee', 'gees', 'acceleration_due_to_gravity',
|
||||
'u0', 'magnetic_constant', 'vacuum_permeability',
|
||||
'e0', 'electric_constant', 'vacuum_permittivity',
|
||||
'Z0', 'vacuum_impedance',
|
||||
'coulomb_constant', 'electric_force_constant',
|
||||
'atmosphere', 'atmospheres', 'atm',
|
||||
'kPa',
|
||||
'bar', 'bars',
|
||||
'pound', 'pounds',
|
||||
'psi',
|
||||
'dHg0',
|
||||
'mmHg', 'torr',
|
||||
'mmu', 'mmus', 'milli_mass_unit',
|
||||
'quart', 'quarts',
|
||||
'ly', 'lightyear', 'lightyears',
|
||||
'au', 'astronomical_unit', 'astronomical_units',
|
||||
'planck_mass',
|
||||
'planck_time',
|
||||
'planck_temperature',
|
||||
'planck_length',
|
||||
'planck_charge',
|
||||
'planck_area',
|
||||
'planck_volume',
|
||||
'planck_momentum',
|
||||
'planck_energy',
|
||||
'planck_force',
|
||||
'planck_power',
|
||||
'planck_density',
|
||||
'planck_energy_density',
|
||||
'planck_intensity',
|
||||
'planck_angular_frequency',
|
||||
'planck_pressure',
|
||||
'planck_current',
|
||||
'planck_voltage',
|
||||
'planck_impedance',
|
||||
'planck_acceleration',
|
||||
'bit', 'bits',
|
||||
'byte',
|
||||
'kibibyte', 'kibibytes',
|
||||
'mebibyte', 'mebibytes',
|
||||
'gibibyte', 'gibibytes',
|
||||
'tebibyte', 'tebibytes',
|
||||
'pebibyte', 'pebibytes',
|
||||
'exbibyte', 'exbibytes',
|
||||
|
||||
'mks', 'mksa', 'si',
|
||||
]
|
||||
@@ -0,0 +1,265 @@
|
||||
from .unit_definitions import (
|
||||
percent, percents,
|
||||
permille,
|
||||
rad, radian, radians,
|
||||
deg, degree, degrees,
|
||||
sr, steradian, steradians,
|
||||
mil, angular_mil, angular_mils,
|
||||
m, meter, meters,
|
||||
kg, kilogram, kilograms,
|
||||
s, second, seconds,
|
||||
A, ampere, amperes,
|
||||
K, kelvin, kelvins,
|
||||
mol, mole, moles,
|
||||
cd, candela, candelas,
|
||||
g, gram, grams,
|
||||
mg, milligram, milligrams,
|
||||
ug, microgram, micrograms,
|
||||
t, tonne, metric_ton,
|
||||
newton, newtons, N,
|
||||
joule, joules, J,
|
||||
watt, watts, W,
|
||||
pascal, pascals, Pa, pa,
|
||||
hertz, hz, Hz,
|
||||
coulomb, coulombs, C,
|
||||
volt, volts, v, V,
|
||||
ohm, ohms,
|
||||
siemens, S, mho, mhos,
|
||||
farad, farads, F,
|
||||
henry, henrys, H,
|
||||
tesla, teslas, T,
|
||||
weber, webers, Wb, wb,
|
||||
optical_power, dioptre, D,
|
||||
lux, lx,
|
||||
katal, kat,
|
||||
gray, Gy,
|
||||
becquerel, Bq,
|
||||
km, kilometer, kilometers,
|
||||
dm, decimeter, decimeters,
|
||||
cm, centimeter, centimeters,
|
||||
mm, millimeter, millimeters,
|
||||
um, micrometer, micrometers, micron, microns,
|
||||
nm, nanometer, nanometers,
|
||||
pm, picometer, picometers,
|
||||
ft, foot, feet,
|
||||
inch, inches,
|
||||
yd, yard, yards,
|
||||
mi, mile, miles,
|
||||
nmi, nautical_mile, nautical_miles,
|
||||
ha, hectare,
|
||||
l, L, liter, liters,
|
||||
dl, dL, deciliter, deciliters,
|
||||
cl, cL, centiliter, centiliters,
|
||||
ml, mL, milliliter, milliliters,
|
||||
ms, millisecond, milliseconds,
|
||||
us, microsecond, microseconds,
|
||||
ns, nanosecond, nanoseconds,
|
||||
ps, picosecond, picoseconds,
|
||||
minute, minutes,
|
||||
h, hour, hours,
|
||||
day, days,
|
||||
anomalistic_year, anomalistic_years,
|
||||
sidereal_year, sidereal_years,
|
||||
tropical_year, tropical_years,
|
||||
common_year, common_years,
|
||||
julian_year, julian_years,
|
||||
draconic_year, draconic_years,
|
||||
gaussian_year, gaussian_years,
|
||||
full_moon_cycle, full_moon_cycles,
|
||||
year, years,
|
||||
G, gravitational_constant,
|
||||
c, speed_of_light,
|
||||
elementary_charge,
|
||||
hbar,
|
||||
planck,
|
||||
eV, electronvolt, electronvolts,
|
||||
avogadro_number,
|
||||
avogadro, avogadro_constant,
|
||||
boltzmann, boltzmann_constant,
|
||||
stefan, stefan_boltzmann_constant,
|
||||
R, molar_gas_constant,
|
||||
faraday_constant,
|
||||
josephson_constant,
|
||||
von_klitzing_constant,
|
||||
Da, dalton, amu, amus, atomic_mass_unit, atomic_mass_constant,
|
||||
me, electron_rest_mass,
|
||||
gee, gees, acceleration_due_to_gravity,
|
||||
u0, magnetic_constant, vacuum_permeability,
|
||||
e0, electric_constant, vacuum_permittivity,
|
||||
Z0, vacuum_impedance,
|
||||
coulomb_constant, coulombs_constant, electric_force_constant,
|
||||
atmosphere, atmospheres, atm,
|
||||
kPa, kilopascal,
|
||||
bar, bars,
|
||||
pound, pounds,
|
||||
psi,
|
||||
dHg0,
|
||||
mmHg, torr,
|
||||
mmu, mmus, milli_mass_unit,
|
||||
quart, quarts,
|
||||
angstrom, angstroms,
|
||||
ly, lightyear, lightyears,
|
||||
au, astronomical_unit, astronomical_units,
|
||||
planck_mass,
|
||||
planck_time,
|
||||
planck_temperature,
|
||||
planck_length,
|
||||
planck_charge,
|
||||
planck_area,
|
||||
planck_volume,
|
||||
planck_momentum,
|
||||
planck_energy,
|
||||
planck_force,
|
||||
planck_power,
|
||||
planck_density,
|
||||
planck_energy_density,
|
||||
planck_intensity,
|
||||
planck_angular_frequency,
|
||||
planck_pressure,
|
||||
planck_current,
|
||||
planck_voltage,
|
||||
planck_impedance,
|
||||
planck_acceleration,
|
||||
bit, bits,
|
||||
byte,
|
||||
kibibyte, kibibytes,
|
||||
mebibyte, mebibytes,
|
||||
gibibyte, gibibytes,
|
||||
tebibyte, tebibytes,
|
||||
pebibyte, pebibytes,
|
||||
exbibyte, exbibytes,
|
||||
curie, rutherford
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'percent', 'percents',
|
||||
'permille',
|
||||
'rad', 'radian', 'radians',
|
||||
'deg', 'degree', 'degrees',
|
||||
'sr', 'steradian', 'steradians',
|
||||
'mil', 'angular_mil', 'angular_mils',
|
||||
'm', 'meter', 'meters',
|
||||
'kg', 'kilogram', 'kilograms',
|
||||
's', 'second', 'seconds',
|
||||
'A', 'ampere', 'amperes',
|
||||
'K', 'kelvin', 'kelvins',
|
||||
'mol', 'mole', 'moles',
|
||||
'cd', 'candela', 'candelas',
|
||||
'g', 'gram', 'grams',
|
||||
'mg', 'milligram', 'milligrams',
|
||||
'ug', 'microgram', 'micrograms',
|
||||
't', 'tonne', 'metric_ton',
|
||||
'newton', 'newtons', 'N',
|
||||
'joule', 'joules', 'J',
|
||||
'watt', 'watts', 'W',
|
||||
'pascal', 'pascals', 'Pa', 'pa',
|
||||
'hertz', 'hz', 'Hz',
|
||||
'coulomb', 'coulombs', 'C',
|
||||
'volt', 'volts', 'v', 'V',
|
||||
'ohm', 'ohms',
|
||||
'siemens', 'S', 'mho', 'mhos',
|
||||
'farad', 'farads', 'F',
|
||||
'henry', 'henrys', 'H',
|
||||
'tesla', 'teslas', 'T',
|
||||
'weber', 'webers', 'Wb', 'wb',
|
||||
'optical_power', 'dioptre', 'D',
|
||||
'lux', 'lx',
|
||||
'katal', 'kat',
|
||||
'gray', 'Gy',
|
||||
'becquerel', 'Bq',
|
||||
'km', 'kilometer', 'kilometers',
|
||||
'dm', 'decimeter', 'decimeters',
|
||||
'cm', 'centimeter', 'centimeters',
|
||||
'mm', 'millimeter', 'millimeters',
|
||||
'um', 'micrometer', 'micrometers', 'micron', 'microns',
|
||||
'nm', 'nanometer', 'nanometers',
|
||||
'pm', 'picometer', 'picometers',
|
||||
'ft', 'foot', 'feet',
|
||||
'inch', 'inches',
|
||||
'yd', 'yard', 'yards',
|
||||
'mi', 'mile', 'miles',
|
||||
'nmi', 'nautical_mile', 'nautical_miles',
|
||||
'ha', 'hectare',
|
||||
'l', 'L', 'liter', 'liters',
|
||||
'dl', 'dL', 'deciliter', 'deciliters',
|
||||
'cl', 'cL', 'centiliter', 'centiliters',
|
||||
'ml', 'mL', 'milliliter', 'milliliters',
|
||||
'ms', 'millisecond', 'milliseconds',
|
||||
'us', 'microsecond', 'microseconds',
|
||||
'ns', 'nanosecond', 'nanoseconds',
|
||||
'ps', 'picosecond', 'picoseconds',
|
||||
'minute', 'minutes',
|
||||
'h', 'hour', 'hours',
|
||||
'day', 'days',
|
||||
'anomalistic_year', 'anomalistic_years',
|
||||
'sidereal_year', 'sidereal_years',
|
||||
'tropical_year', 'tropical_years',
|
||||
'common_year', 'common_years',
|
||||
'julian_year', 'julian_years',
|
||||
'draconic_year', 'draconic_years',
|
||||
'gaussian_year', 'gaussian_years',
|
||||
'full_moon_cycle', 'full_moon_cycles',
|
||||
'year', 'years',
|
||||
'G', 'gravitational_constant',
|
||||
'c', 'speed_of_light',
|
||||
'elementary_charge',
|
||||
'hbar',
|
||||
'planck',
|
||||
'eV', 'electronvolt', 'electronvolts',
|
||||
'avogadro_number',
|
||||
'avogadro', 'avogadro_constant',
|
||||
'boltzmann', 'boltzmann_constant',
|
||||
'stefan', 'stefan_boltzmann_constant',
|
||||
'R', 'molar_gas_constant',
|
||||
'faraday_constant',
|
||||
'josephson_constant',
|
||||
'von_klitzing_constant',
|
||||
'Da', 'dalton', 'amu', 'amus', 'atomic_mass_unit', 'atomic_mass_constant',
|
||||
'me', 'electron_rest_mass',
|
||||
'gee', 'gees', 'acceleration_due_to_gravity',
|
||||
'u0', 'magnetic_constant', 'vacuum_permeability',
|
||||
'e0', 'electric_constant', 'vacuum_permittivity',
|
||||
'Z0', 'vacuum_impedance',
|
||||
'coulomb_constant', 'coulombs_constant', 'electric_force_constant',
|
||||
'atmosphere', 'atmospheres', 'atm',
|
||||
'kPa', 'kilopascal',
|
||||
'bar', 'bars',
|
||||
'pound', 'pounds',
|
||||
'psi',
|
||||
'dHg0',
|
||||
'mmHg', 'torr',
|
||||
'mmu', 'mmus', 'milli_mass_unit',
|
||||
'quart', 'quarts',
|
||||
'angstrom', 'angstroms',
|
||||
'ly', 'lightyear', 'lightyears',
|
||||
'au', 'astronomical_unit', 'astronomical_units',
|
||||
'planck_mass',
|
||||
'planck_time',
|
||||
'planck_temperature',
|
||||
'planck_length',
|
||||
'planck_charge',
|
||||
'planck_area',
|
||||
'planck_volume',
|
||||
'planck_momentum',
|
||||
'planck_energy',
|
||||
'planck_force',
|
||||
'planck_power',
|
||||
'planck_density',
|
||||
'planck_energy_density',
|
||||
'planck_intensity',
|
||||
'planck_angular_frequency',
|
||||
'planck_pressure',
|
||||
'planck_current',
|
||||
'planck_voltage',
|
||||
'planck_impedance',
|
||||
'planck_acceleration',
|
||||
'bit', 'bits',
|
||||
'byte',
|
||||
'kibibyte', 'kibibytes',
|
||||
'mebibyte', 'mebibytes',
|
||||
'gibibyte', 'gibibytes',
|
||||
'tebibyte', 'tebibytes',
|
||||
'pebibyte', 'pebibytes',
|
||||
'exbibyte', 'exbibytes',
|
||||
'curie', 'rutherford',
|
||||
]
|
||||
@@ -0,0 +1,43 @@
|
||||
from sympy.physics.units import Dimension
|
||||
|
||||
|
||||
angle: Dimension = Dimension(name="angle")
|
||||
|
||||
# base dimensions (MKS)
|
||||
length = Dimension(name="length", symbol="L")
|
||||
mass = Dimension(name="mass", symbol="M")
|
||||
time = Dimension(name="time", symbol="T")
|
||||
|
||||
# base dimensions (MKSA not in MKS)
|
||||
current: Dimension = Dimension(name='current', symbol='I')
|
||||
|
||||
# other base dimensions:
|
||||
temperature: Dimension = Dimension("temperature", "T")
|
||||
amount_of_substance: Dimension = Dimension("amount_of_substance")
|
||||
luminous_intensity: Dimension = Dimension("luminous_intensity")
|
||||
|
||||
# derived dimensions (MKS)
|
||||
velocity = Dimension(name="velocity")
|
||||
acceleration = Dimension(name="acceleration")
|
||||
momentum = Dimension(name="momentum")
|
||||
force = Dimension(name="force", symbol="F")
|
||||
energy = Dimension(name="energy", symbol="E")
|
||||
power = Dimension(name="power")
|
||||
pressure = Dimension(name="pressure")
|
||||
frequency = Dimension(name="frequency", symbol="f")
|
||||
action = Dimension(name="action", symbol="A")
|
||||
area = Dimension("area")
|
||||
volume = Dimension("volume")
|
||||
|
||||
# derived dimensions (MKSA not in MKS)
|
||||
voltage: Dimension = Dimension(name='voltage', symbol='U')
|
||||
impedance: Dimension = Dimension(name='impedance', symbol='Z')
|
||||
conductance: Dimension = Dimension(name='conductance', symbol='G')
|
||||
capacitance: Dimension = Dimension(name='capacitance')
|
||||
inductance: Dimension = Dimension(name='inductance')
|
||||
charge: Dimension = Dimension(name='charge', symbol='Q')
|
||||
magnetic_density: Dimension = Dimension(name='magnetic_density', symbol='B')
|
||||
magnetic_flux: Dimension = Dimension(name='magnetic_flux')
|
||||
|
||||
# Dimensions in information theory:
|
||||
information: Dimension = Dimension(name='information')
|
||||
@@ -0,0 +1,407 @@
|
||||
from sympy.physics.units.definitions.dimension_definitions import current, temperature, amount_of_substance, \
|
||||
luminous_intensity, angle, charge, voltage, impedance, conductance, capacitance, inductance, magnetic_density, \
|
||||
magnetic_flux, information
|
||||
|
||||
from sympy.core.numbers import (Rational, pi)
|
||||
from sympy.core.singleton import S as S_singleton
|
||||
from sympy.physics.units.prefixes import kilo, mega, milli, micro, deci, centi, nano, pico, kibi, mebi, gibi, tebi, pebi, exbi
|
||||
from sympy.physics.units.quantities import PhysicalConstant, Quantity
|
||||
|
||||
One = S_singleton.One
|
||||
|
||||
#### UNITS ####
|
||||
|
||||
# Dimensionless:
|
||||
percent = percents = Quantity("percent", latex_repr=r"\%")
|
||||
percent.set_global_relative_scale_factor(Rational(1, 100), One)
|
||||
|
||||
permille = Quantity("permille")
|
||||
permille.set_global_relative_scale_factor(Rational(1, 1000), One)
|
||||
|
||||
|
||||
# Angular units (dimensionless)
|
||||
rad = radian = radians = Quantity("radian", abbrev="rad")
|
||||
radian.set_global_dimension(angle)
|
||||
deg = degree = degrees = Quantity("degree", abbrev="deg", latex_repr=r"^\circ")
|
||||
degree.set_global_relative_scale_factor(pi/180, radian)
|
||||
sr = steradian = steradians = Quantity("steradian", abbrev="sr")
|
||||
mil = angular_mil = angular_mils = Quantity("angular_mil", abbrev="mil")
|
||||
|
||||
# Base units:
|
||||
m = meter = meters = Quantity("meter", abbrev="m")
|
||||
|
||||
# gram; used to define its prefixed units
|
||||
g = gram = grams = Quantity("gram", abbrev="g")
|
||||
|
||||
# NOTE: the `kilogram` has scale factor 1000. In SI, kg is a base unit, but
|
||||
# nonetheless we are trying to be compatible with the `kilo` prefix. In a
|
||||
# similar manner, people using CGS or gaussian units could argue that the
|
||||
# `centimeter` rather than `meter` is the fundamental unit for length, but the
|
||||
# scale factor of `centimeter` will be kept as 1/100 to be compatible with the
|
||||
# `centi` prefix. The current state of the code assumes SI unit dimensions, in
|
||||
# the future this module will be modified in order to be unit system-neutral
|
||||
# (that is, support all kinds of unit systems).
|
||||
kg = kilogram = kilograms = Quantity("kilogram", abbrev="kg")
|
||||
kg.set_global_relative_scale_factor(kilo, gram)
|
||||
|
||||
s = second = seconds = Quantity("second", abbrev="s")
|
||||
A = ampere = amperes = Quantity("ampere", abbrev='A')
|
||||
ampere.set_global_dimension(current)
|
||||
K = kelvin = kelvins = Quantity("kelvin", abbrev='K')
|
||||
kelvin.set_global_dimension(temperature)
|
||||
mol = mole = moles = Quantity("mole", abbrev="mol")
|
||||
mole.set_global_dimension(amount_of_substance)
|
||||
cd = candela = candelas = Quantity("candela", abbrev="cd")
|
||||
candela.set_global_dimension(luminous_intensity)
|
||||
|
||||
# derived units
|
||||
newton = newtons = N = Quantity("newton", abbrev="N")
|
||||
|
||||
kilonewton = kilonewtons = kN = Quantity("kilonewton", abbrev="kN")
|
||||
kilonewton.set_global_relative_scale_factor(kilo, newton)
|
||||
|
||||
meganewton = meganewtons = MN = Quantity("meganewton", abbrev="MN")
|
||||
meganewton.set_global_relative_scale_factor(mega, newton)
|
||||
|
||||
joule = joules = J = Quantity("joule", abbrev="J")
|
||||
watt = watts = W = Quantity("watt", abbrev="W")
|
||||
pascal = pascals = Pa = pa = Quantity("pascal", abbrev="Pa")
|
||||
hertz = hz = Hz = Quantity("hertz", abbrev="Hz")
|
||||
|
||||
# CGS derived units:
|
||||
dyne = Quantity("dyne")
|
||||
dyne.set_global_relative_scale_factor(One/10**5, newton)
|
||||
erg = Quantity("erg")
|
||||
erg.set_global_relative_scale_factor(One/10**7, joule)
|
||||
|
||||
# MKSA extension to MKS: derived units
|
||||
coulomb = coulombs = C = Quantity("coulomb", abbrev='C')
|
||||
coulomb.set_global_dimension(charge)
|
||||
volt = volts = v = V = Quantity("volt", abbrev='V')
|
||||
volt.set_global_dimension(voltage)
|
||||
ohm = ohms = Quantity("ohm", abbrev='ohm', latex_repr=r"\Omega")
|
||||
ohm.set_global_dimension(impedance)
|
||||
siemens = S = mho = mhos = Quantity("siemens", abbrev='S')
|
||||
siemens.set_global_dimension(conductance)
|
||||
farad = farads = F = Quantity("farad", abbrev='F')
|
||||
farad.set_global_dimension(capacitance)
|
||||
henry = henrys = H = Quantity("henry", abbrev='H')
|
||||
henry.set_global_dimension(inductance)
|
||||
tesla = teslas = T = Quantity("tesla", abbrev='T')
|
||||
tesla.set_global_dimension(magnetic_density)
|
||||
weber = webers = Wb = wb = Quantity("weber", abbrev='Wb')
|
||||
weber.set_global_dimension(magnetic_flux)
|
||||
|
||||
# CGS units for electromagnetic quantities:
|
||||
statampere = Quantity("statampere")
|
||||
statcoulomb = statC = franklin = Quantity("statcoulomb", abbrev="statC")
|
||||
statvolt = Quantity("statvolt")
|
||||
gauss = Quantity("gauss")
|
||||
maxwell = Quantity("maxwell")
|
||||
debye = Quantity("debye")
|
||||
oersted = Quantity("oersted")
|
||||
|
||||
# Other derived units:
|
||||
optical_power = dioptre = diopter = D = Quantity("dioptre")
|
||||
lux = lx = Quantity("lux", abbrev="lx")
|
||||
|
||||
# katal is the SI unit of catalytic activity
|
||||
katal = kat = Quantity("katal", abbrev="kat")
|
||||
|
||||
# gray is the SI unit of absorbed dose
|
||||
gray = Gy = Quantity("gray")
|
||||
|
||||
# becquerel is the SI unit of radioactivity
|
||||
becquerel = Bq = Quantity("becquerel", abbrev="Bq")
|
||||
|
||||
|
||||
# Common mass units
|
||||
|
||||
mg = milligram = milligrams = Quantity("milligram", abbrev="mg")
|
||||
mg.set_global_relative_scale_factor(milli, gram)
|
||||
|
||||
ug = microgram = micrograms = Quantity("microgram", abbrev="ug", latex_repr=r"\mu\text{g}")
|
||||
ug.set_global_relative_scale_factor(micro, gram)
|
||||
|
||||
# Atomic mass constant
|
||||
Da = dalton = amu = amus = atomic_mass_unit = atomic_mass_constant = PhysicalConstant("atomic_mass_constant")
|
||||
|
||||
t = metric_ton = tonne = Quantity("tonne", abbrev="t")
|
||||
tonne.set_global_relative_scale_factor(mega, gram)
|
||||
|
||||
# Electron rest mass
|
||||
me = electron_rest_mass = Quantity("electron_rest_mass", abbrev="me")
|
||||
|
||||
|
||||
# Common length units
|
||||
|
||||
km = kilometer = kilometers = Quantity("kilometer", abbrev="km")
|
||||
km.set_global_relative_scale_factor(kilo, meter)
|
||||
|
||||
dm = decimeter = decimeters = Quantity("decimeter", abbrev="dm")
|
||||
dm.set_global_relative_scale_factor(deci, meter)
|
||||
|
||||
cm = centimeter = centimeters = Quantity("centimeter", abbrev="cm")
|
||||
cm.set_global_relative_scale_factor(centi, meter)
|
||||
|
||||
mm = millimeter = millimeters = Quantity("millimeter", abbrev="mm")
|
||||
mm.set_global_relative_scale_factor(milli, meter)
|
||||
|
||||
um = micrometer = micrometers = micron = microns = \
|
||||
Quantity("micrometer", abbrev="um", latex_repr=r'\mu\text{m}')
|
||||
um.set_global_relative_scale_factor(micro, meter)
|
||||
|
||||
nm = nanometer = nanometers = Quantity("nanometer", abbrev="nm")
|
||||
nm.set_global_relative_scale_factor(nano, meter)
|
||||
|
||||
pm = picometer = picometers = Quantity("picometer", abbrev="pm")
|
||||
pm.set_global_relative_scale_factor(pico, meter)
|
||||
|
||||
ft = foot = feet = Quantity("foot", abbrev="ft")
|
||||
ft.set_global_relative_scale_factor(Rational(3048, 10000), meter)
|
||||
|
||||
inch = inches = Quantity("inch")
|
||||
inch.set_global_relative_scale_factor(Rational(1, 12), foot)
|
||||
|
||||
yd = yard = yards = Quantity("yard", abbrev="yd")
|
||||
yd.set_global_relative_scale_factor(3, feet)
|
||||
|
||||
mi = mile = miles = Quantity("mile")
|
||||
mi.set_global_relative_scale_factor(5280, feet)
|
||||
|
||||
nmi = nautical_mile = nautical_miles = Quantity("nautical_mile")
|
||||
nmi.set_global_relative_scale_factor(6076, feet)
|
||||
|
||||
angstrom = angstroms = Quantity("angstrom", latex_repr=r'\r{A}')
|
||||
angstrom.set_global_relative_scale_factor(Rational(1, 10**10), meter)
|
||||
|
||||
|
||||
# Common volume and area units
|
||||
|
||||
ha = hectare = Quantity("hectare", abbrev="ha")
|
||||
|
||||
l = L = liter = liters = Quantity("liter", abbrev="l")
|
||||
|
||||
dl = dL = deciliter = deciliters = Quantity("deciliter", abbrev="dl")
|
||||
dl.set_global_relative_scale_factor(Rational(1, 10), liter)
|
||||
|
||||
cl = cL = centiliter = centiliters = Quantity("centiliter", abbrev="cl")
|
||||
cl.set_global_relative_scale_factor(Rational(1, 100), liter)
|
||||
|
||||
ml = mL = milliliter = milliliters = Quantity("milliliter", abbrev="ml")
|
||||
ml.set_global_relative_scale_factor(Rational(1, 1000), liter)
|
||||
|
||||
|
||||
# Common time units
|
||||
|
||||
ms = millisecond = milliseconds = Quantity("millisecond", abbrev="ms")
|
||||
millisecond.set_global_relative_scale_factor(milli, second)
|
||||
|
||||
us = microsecond = microseconds = Quantity("microsecond", abbrev="us", latex_repr=r'\mu\text{s}')
|
||||
microsecond.set_global_relative_scale_factor(micro, second)
|
||||
|
||||
ns = nanosecond = nanoseconds = Quantity("nanosecond", abbrev="ns")
|
||||
nanosecond.set_global_relative_scale_factor(nano, second)
|
||||
|
||||
ps = picosecond = picoseconds = Quantity("picosecond", abbrev="ps")
|
||||
picosecond.set_global_relative_scale_factor(pico, second)
|
||||
|
||||
minute = minutes = Quantity("minute")
|
||||
minute.set_global_relative_scale_factor(60, second)
|
||||
|
||||
h = hour = hours = Quantity("hour")
|
||||
hour.set_global_relative_scale_factor(60, minute)
|
||||
|
||||
day = days = Quantity("day")
|
||||
day.set_global_relative_scale_factor(24, hour)
|
||||
|
||||
anomalistic_year = anomalistic_years = Quantity("anomalistic_year")
|
||||
anomalistic_year.set_global_relative_scale_factor(365.259636, day)
|
||||
|
||||
sidereal_year = sidereal_years = Quantity("sidereal_year")
|
||||
sidereal_year.set_global_relative_scale_factor(31558149.540, seconds)
|
||||
|
||||
tropical_year = tropical_years = Quantity("tropical_year")
|
||||
tropical_year.set_global_relative_scale_factor(365.24219, day)
|
||||
|
||||
common_year = common_years = Quantity("common_year")
|
||||
common_year.set_global_relative_scale_factor(365, day)
|
||||
|
||||
julian_year = julian_years = Quantity("julian_year")
|
||||
julian_year.set_global_relative_scale_factor((365 + One/4), day)
|
||||
|
||||
draconic_year = draconic_years = Quantity("draconic_year")
|
||||
draconic_year.set_global_relative_scale_factor(346.62, day)
|
||||
|
||||
gaussian_year = gaussian_years = Quantity("gaussian_year")
|
||||
gaussian_year.set_global_relative_scale_factor(365.2568983, day)
|
||||
|
||||
full_moon_cycle = full_moon_cycles = Quantity("full_moon_cycle")
|
||||
full_moon_cycle.set_global_relative_scale_factor(411.78443029, day)
|
||||
|
||||
year = years = tropical_year
|
||||
|
||||
|
||||
#### CONSTANTS ####
|
||||
|
||||
# Newton constant
|
||||
G = gravitational_constant = PhysicalConstant("gravitational_constant", abbrev="G")
|
||||
|
||||
# speed of light
|
||||
c = speed_of_light = PhysicalConstant("speed_of_light", abbrev="c")
|
||||
|
||||
# elementary charge
|
||||
elementary_charge = PhysicalConstant("elementary_charge", abbrev="e")
|
||||
|
||||
# Planck constant
|
||||
planck = PhysicalConstant("planck", abbrev="h")
|
||||
|
||||
# Reduced Planck constant
|
||||
hbar = PhysicalConstant("hbar", abbrev="hbar")
|
||||
|
||||
# Electronvolt
|
||||
eV = electronvolt = electronvolts = PhysicalConstant("electronvolt", abbrev="eV")
|
||||
|
||||
# Avogadro number
|
||||
avogadro_number = PhysicalConstant("avogadro_number")
|
||||
|
||||
# Avogadro constant
|
||||
avogadro = avogadro_constant = PhysicalConstant("avogadro_constant")
|
||||
|
||||
# Boltzmann constant
|
||||
boltzmann = boltzmann_constant = PhysicalConstant("boltzmann_constant")
|
||||
|
||||
# Stefan-Boltzmann constant
|
||||
stefan = stefan_boltzmann_constant = PhysicalConstant("stefan_boltzmann_constant")
|
||||
|
||||
# Molar gas constant
|
||||
R = molar_gas_constant = PhysicalConstant("molar_gas_constant", abbrev="R")
|
||||
|
||||
# Faraday constant
|
||||
faraday_constant = PhysicalConstant("faraday_constant")
|
||||
|
||||
# Josephson constant
|
||||
josephson_constant = PhysicalConstant("josephson_constant", abbrev="K_j")
|
||||
|
||||
# Von Klitzing constant
|
||||
von_klitzing_constant = PhysicalConstant("von_klitzing_constant", abbrev="R_k")
|
||||
|
||||
# Acceleration due to gravity (on the Earth surface)
|
||||
gee = gees = acceleration_due_to_gravity = PhysicalConstant("acceleration_due_to_gravity", abbrev="g")
|
||||
|
||||
# magnetic constant:
|
||||
u0 = magnetic_constant = vacuum_permeability = PhysicalConstant("magnetic_constant")
|
||||
|
||||
# electric constat:
|
||||
e0 = electric_constant = vacuum_permittivity = PhysicalConstant("vacuum_permittivity")
|
||||
|
||||
# vacuum impedance:
|
||||
Z0 = vacuum_impedance = PhysicalConstant("vacuum_impedance", abbrev='Z_0', latex_repr=r'Z_{0}')
|
||||
|
||||
# Coulomb's constant:
|
||||
coulomb_constant = coulombs_constant = electric_force_constant = \
|
||||
PhysicalConstant("coulomb_constant", abbrev="k_e")
|
||||
|
||||
|
||||
atmosphere = atmospheres = atm = Quantity("atmosphere", abbrev="atm")
|
||||
|
||||
kPa = kilopascal = Quantity("kilopascal", abbrev="kPa")
|
||||
kilopascal.set_global_relative_scale_factor(kilo, Pa)
|
||||
|
||||
bar = bars = Quantity("bar", abbrev="bar")
|
||||
|
||||
pound = pounds = Quantity("pound") # exact
|
||||
|
||||
psi = Quantity("psi")
|
||||
|
||||
dHg0 = 13.5951 # approx value at 0 C
|
||||
mmHg = torr = Quantity("mmHg")
|
||||
|
||||
atmosphere.set_global_relative_scale_factor(101325, pascal)
|
||||
bar.set_global_relative_scale_factor(100, kPa)
|
||||
pound.set_global_relative_scale_factor(Rational(45359237, 100000000), kg)
|
||||
|
||||
mmu = mmus = milli_mass_unit = Quantity("milli_mass_unit")
|
||||
|
||||
quart = quarts = Quantity("quart")
|
||||
|
||||
|
||||
# Other convenient units and magnitudes
|
||||
|
||||
ly = lightyear = lightyears = Quantity("lightyear", abbrev="ly")
|
||||
|
||||
au = astronomical_unit = astronomical_units = Quantity("astronomical_unit", abbrev="AU")
|
||||
|
||||
|
||||
# Fundamental Planck units:
|
||||
planck_mass = Quantity("planck_mass", abbrev="m_P", latex_repr=r'm_\text{P}')
|
||||
|
||||
planck_time = Quantity("planck_time", abbrev="t_P", latex_repr=r't_\text{P}')
|
||||
|
||||
planck_temperature = Quantity("planck_temperature", abbrev="T_P",
|
||||
latex_repr=r'T_\text{P}')
|
||||
|
||||
planck_length = Quantity("planck_length", abbrev="l_P", latex_repr=r'l_\text{P}')
|
||||
|
||||
planck_charge = Quantity("planck_charge", abbrev="q_P", latex_repr=r'q_\text{P}')
|
||||
|
||||
|
||||
# Derived Planck units:
|
||||
planck_area = Quantity("planck_area")
|
||||
|
||||
planck_volume = Quantity("planck_volume")
|
||||
|
||||
planck_momentum = Quantity("planck_momentum")
|
||||
|
||||
planck_energy = Quantity("planck_energy", abbrev="E_P", latex_repr=r'E_\text{P}')
|
||||
|
||||
planck_force = Quantity("planck_force", abbrev="F_P", latex_repr=r'F_\text{P}')
|
||||
|
||||
planck_power = Quantity("planck_power", abbrev="P_P", latex_repr=r'P_\text{P}')
|
||||
|
||||
planck_density = Quantity("planck_density", abbrev="rho_P", latex_repr=r'\rho_\text{P}')
|
||||
|
||||
planck_energy_density = Quantity("planck_energy_density", abbrev="rho^E_P")
|
||||
|
||||
planck_intensity = Quantity("planck_intensity", abbrev="I_P", latex_repr=r'I_\text{P}')
|
||||
|
||||
planck_angular_frequency = Quantity("planck_angular_frequency", abbrev="omega_P",
|
||||
latex_repr=r'\omega_\text{P}')
|
||||
|
||||
planck_pressure = Quantity("planck_pressure", abbrev="p_P", latex_repr=r'p_\text{P}')
|
||||
|
||||
planck_current = Quantity("planck_current", abbrev="I_P", latex_repr=r'I_\text{P}')
|
||||
|
||||
planck_voltage = Quantity("planck_voltage", abbrev="V_P", latex_repr=r'V_\text{P}')
|
||||
|
||||
planck_impedance = Quantity("planck_impedance", abbrev="Z_P", latex_repr=r'Z_\text{P}')
|
||||
|
||||
planck_acceleration = Quantity("planck_acceleration", abbrev="a_P",
|
||||
latex_repr=r'a_\text{P}')
|
||||
|
||||
|
||||
# Information theory units:
|
||||
bit = bits = Quantity("bit")
|
||||
bit.set_global_dimension(information)
|
||||
|
||||
byte = bytes = Quantity("byte")
|
||||
|
||||
kibibyte = kibibytes = Quantity("kibibyte")
|
||||
mebibyte = mebibytes = Quantity("mebibyte")
|
||||
gibibyte = gibibytes = Quantity("gibibyte")
|
||||
tebibyte = tebibytes = Quantity("tebibyte")
|
||||
pebibyte = pebibytes = Quantity("pebibyte")
|
||||
exbibyte = exbibytes = Quantity("exbibyte")
|
||||
|
||||
byte.set_global_relative_scale_factor(8, bit)
|
||||
kibibyte.set_global_relative_scale_factor(kibi, byte)
|
||||
mebibyte.set_global_relative_scale_factor(mebi, byte)
|
||||
gibibyte.set_global_relative_scale_factor(gibi, byte)
|
||||
tebibyte.set_global_relative_scale_factor(tebi, byte)
|
||||
pebibyte.set_global_relative_scale_factor(pebi, byte)
|
||||
exbibyte.set_global_relative_scale_factor(exbi, byte)
|
||||
|
||||
# Older units for radioactivity
|
||||
curie = Ci = Quantity("curie", abbrev="Ci")
|
||||
|
||||
rutherford = Rd = Quantity("rutherford", abbrev="Rd")
|
||||
@@ -0,0 +1,590 @@
|
||||
"""
|
||||
Definition of physical dimensions.
|
||||
|
||||
Unit systems will be constructed on top of these dimensions.
|
||||
|
||||
Most of the examples in the doc use MKS system and are presented from the
|
||||
computer point of view: from a human point, adding length to time is not legal
|
||||
in MKS but it is in natural system; for a computer in natural system there is
|
||||
no time dimension (but a velocity dimension instead) - in the basis - so the
|
||||
question of adding time to length has no meaning.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import collections
|
||||
from functools import reduce
|
||||
|
||||
from sympy.core.basic import Basic
|
||||
from sympy.core.containers import (Dict, Tuple)
|
||||
from sympy.core.singleton import S
|
||||
from sympy.core.sorting import default_sort_key
|
||||
from sympy.core.symbol import Symbol
|
||||
from sympy.core.sympify import sympify
|
||||
from sympy.matrices.dense import Matrix
|
||||
from sympy.functions.elementary.trigonometric import TrigonometricFunction
|
||||
from sympy.core.expr import Expr
|
||||
from sympy.core.power import Pow
|
||||
|
||||
|
||||
class _QuantityMapper:
|
||||
|
||||
_quantity_scale_factors_global: dict[Expr, Expr] = {}
|
||||
_quantity_dimensional_equivalence_map_global: dict[Expr, Expr] = {}
|
||||
_quantity_dimension_global: dict[Expr, Expr] = {}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._quantity_dimension_map = {}
|
||||
self._quantity_scale_factors = {}
|
||||
|
||||
def set_quantity_dimension(self, quantity, dimension):
|
||||
"""
|
||||
Set the dimension for the quantity in a unit system.
|
||||
|
||||
If this relation is valid in every unit system, use
|
||||
``quantity.set_global_dimension(dimension)`` instead.
|
||||
"""
|
||||
from sympy.physics.units import Quantity
|
||||
dimension = sympify(dimension)
|
||||
if not isinstance(dimension, Dimension):
|
||||
if dimension == 1:
|
||||
dimension = Dimension(1)
|
||||
else:
|
||||
raise ValueError("expected dimension or 1")
|
||||
elif isinstance(dimension, Quantity):
|
||||
dimension = self.get_quantity_dimension(dimension)
|
||||
self._quantity_dimension_map[quantity] = dimension
|
||||
|
||||
def set_quantity_scale_factor(self, quantity, scale_factor):
|
||||
"""
|
||||
Set the scale factor of a quantity relative to another quantity.
|
||||
|
||||
It should be used only once per quantity to just one other quantity,
|
||||
the algorithm will then be able to compute the scale factors to all
|
||||
other quantities.
|
||||
|
||||
In case the scale factor is valid in every unit system, please use
|
||||
``quantity.set_global_relative_scale_factor(scale_factor)`` instead.
|
||||
"""
|
||||
from sympy.physics.units import Quantity
|
||||
from sympy.physics.units.prefixes import Prefix
|
||||
scale_factor = sympify(scale_factor)
|
||||
# replace all prefixes by their ratio to canonical units:
|
||||
scale_factor = scale_factor.replace(
|
||||
lambda x: isinstance(x, Prefix),
|
||||
lambda x: x.scale_factor
|
||||
)
|
||||
# replace all quantities by their ratio to canonical units:
|
||||
scale_factor = scale_factor.replace(
|
||||
lambda x: isinstance(x, Quantity),
|
||||
lambda x: self.get_quantity_scale_factor(x)
|
||||
)
|
||||
self._quantity_scale_factors[quantity] = scale_factor
|
||||
|
||||
def get_quantity_dimension(self, unit):
|
||||
from sympy.physics.units import Quantity
|
||||
# First look-up the local dimension map, then the global one:
|
||||
if unit in self._quantity_dimension_map:
|
||||
return self._quantity_dimension_map[unit]
|
||||
if unit in self._quantity_dimension_global:
|
||||
return self._quantity_dimension_global[unit]
|
||||
if unit in self._quantity_dimensional_equivalence_map_global:
|
||||
dep_unit = self._quantity_dimensional_equivalence_map_global[unit]
|
||||
if isinstance(dep_unit, Quantity):
|
||||
return self.get_quantity_dimension(dep_unit)
|
||||
else:
|
||||
return Dimension(self.get_dimensional_expr(dep_unit))
|
||||
if isinstance(unit, Quantity):
|
||||
return Dimension(unit.name)
|
||||
else:
|
||||
return Dimension(1)
|
||||
|
||||
def get_quantity_scale_factor(self, unit):
|
||||
if unit in self._quantity_scale_factors:
|
||||
return self._quantity_scale_factors[unit]
|
||||
if unit in self._quantity_scale_factors_global:
|
||||
mul_factor, other_unit = self._quantity_scale_factors_global[unit]
|
||||
return mul_factor*self.get_quantity_scale_factor(other_unit)
|
||||
return S.One
|
||||
|
||||
|
||||
class Dimension(Expr):
|
||||
"""
|
||||
This class represent the dimension of a physical quantities.
|
||||
|
||||
The ``Dimension`` constructor takes as parameters a name and an optional
|
||||
symbol.
|
||||
|
||||
For example, in classical mechanics we know that time is different from
|
||||
temperature and dimensions make this difference (but they do not provide
|
||||
any measure of these quantities.
|
||||
|
||||
>>> from sympy.physics.units import Dimension
|
||||
>>> length = Dimension('length')
|
||||
>>> length
|
||||
Dimension(length)
|
||||
>>> time = Dimension('time')
|
||||
>>> time
|
||||
Dimension(time)
|
||||
|
||||
Dimensions can be composed using multiplication, division and
|
||||
exponentiation (by a number) to give new dimensions. Addition and
|
||||
subtraction is defined only when the two objects are the same dimension.
|
||||
|
||||
>>> velocity = length / time
|
||||
>>> velocity
|
||||
Dimension(length/time)
|
||||
|
||||
It is possible to use a dimension system object to get the dimensionsal
|
||||
dependencies of a dimension, for example the dimension system used by the
|
||||
SI units convention can be used:
|
||||
|
||||
>>> from sympy.physics.units.systems.si import dimsys_SI
|
||||
>>> dimsys_SI.get_dimensional_dependencies(velocity)
|
||||
{Dimension(length, L): 1, Dimension(time, T): -1}
|
||||
>>> length + length
|
||||
Dimension(length)
|
||||
>>> l2 = length**2
|
||||
>>> l2
|
||||
Dimension(length**2)
|
||||
>>> dimsys_SI.get_dimensional_dependencies(l2)
|
||||
{Dimension(length, L): 2}
|
||||
|
||||
"""
|
||||
|
||||
_op_priority = 13.0
|
||||
|
||||
# XXX: This doesn't seem to be used anywhere...
|
||||
_dimensional_dependencies = {} # type: ignore
|
||||
|
||||
is_commutative = True
|
||||
is_number = False
|
||||
# make sqrt(M**2) --> M
|
||||
is_positive = True
|
||||
is_real = True
|
||||
|
||||
def __new__(cls, name, symbol=None):
|
||||
|
||||
if isinstance(name, str):
|
||||
name = Symbol(name)
|
||||
else:
|
||||
name = sympify(name)
|
||||
|
||||
if not isinstance(name, Expr):
|
||||
raise TypeError("Dimension name needs to be a valid math expression")
|
||||
|
||||
if isinstance(symbol, str):
|
||||
symbol = Symbol(symbol)
|
||||
elif symbol is not None:
|
||||
assert isinstance(symbol, Symbol)
|
||||
|
||||
obj = Expr.__new__(cls, name)
|
||||
|
||||
obj._name = name
|
||||
obj._symbol = symbol
|
||||
return obj
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def symbol(self):
|
||||
return self._symbol
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Display the string representation of the dimension.
|
||||
"""
|
||||
if self.symbol is None:
|
||||
return "Dimension(%s)" % (self.name)
|
||||
else:
|
||||
return "Dimension(%s, %s)" % (self.name, self.symbol)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __neg__(self):
|
||||
return self
|
||||
|
||||
def __add__(self, other):
|
||||
from sympy.physics.units.quantities import Quantity
|
||||
other = sympify(other)
|
||||
if isinstance(other, Basic):
|
||||
if other.has(Quantity):
|
||||
raise TypeError("cannot sum dimension and quantity")
|
||||
if isinstance(other, Dimension) and self == other:
|
||||
return self
|
||||
return super().__add__(other)
|
||||
return self
|
||||
|
||||
def __radd__(self, other):
|
||||
return self.__add__(other)
|
||||
|
||||
def __sub__(self, other):
|
||||
# there is no notion of ordering (or magnitude) among dimension,
|
||||
# subtraction is equivalent to addition when the operation is legal
|
||||
return self + other
|
||||
|
||||
def __rsub__(self, other):
|
||||
# there is no notion of ordering (or magnitude) among dimension,
|
||||
# subtraction is equivalent to addition when the operation is legal
|
||||
return self + other
|
||||
|
||||
def __pow__(self, other):
|
||||
return self._eval_power(other)
|
||||
|
||||
def _eval_power(self, other):
|
||||
other = sympify(other)
|
||||
return Dimension(self.name**other)
|
||||
|
||||
def __mul__(self, other):
|
||||
from sympy.physics.units.quantities import Quantity
|
||||
if isinstance(other, Basic):
|
||||
if other.has(Quantity):
|
||||
raise TypeError("cannot sum dimension and quantity")
|
||||
if isinstance(other, Dimension):
|
||||
return Dimension(self.name*other.name)
|
||||
if not other.free_symbols: # other.is_number cannot be used
|
||||
return self
|
||||
return super().__mul__(other)
|
||||
return self
|
||||
|
||||
def __rmul__(self, other):
|
||||
return self.__mul__(other)
|
||||
|
||||
def __truediv__(self, other):
|
||||
return self*Pow(other, -1)
|
||||
|
||||
def __rtruediv__(self, other):
|
||||
return other * pow(self, -1)
|
||||
|
||||
@classmethod
|
||||
def _from_dimensional_dependencies(cls, dependencies):
|
||||
return reduce(lambda x, y: x * y, (
|
||||
d**e for d, e in dependencies.items()
|
||||
), 1)
|
||||
|
||||
def has_integer_powers(self, dim_sys):
|
||||
"""
|
||||
Check if the dimension object has only integer powers.
|
||||
|
||||
All the dimension powers should be integers, but rational powers may
|
||||
appear in intermediate steps. This method may be used to check that the
|
||||
final result is well-defined.
|
||||
"""
|
||||
|
||||
return all(dpow.is_Integer for dpow in dim_sys.get_dimensional_dependencies(self).values())
|
||||
|
||||
|
||||
# Create dimensions according to the base units in MKSA.
|
||||
# For other unit systems, they can be derived by transforming the base
|
||||
# dimensional dependency dictionary.
|
||||
|
||||
|
||||
class DimensionSystem(Basic, _QuantityMapper):
|
||||
r"""
|
||||
DimensionSystem represents a coherent set of dimensions.
|
||||
|
||||
The constructor takes three parameters:
|
||||
|
||||
- base dimensions;
|
||||
- derived dimensions: these are defined in terms of the base dimensions
|
||||
(for example velocity is defined from the division of length by time);
|
||||
- dependency of dimensions: how the derived dimensions depend
|
||||
on the base dimensions.
|
||||
|
||||
Optionally either the ``derived_dims`` or the ``dimensional_dependencies``
|
||||
may be omitted.
|
||||
"""
|
||||
|
||||
def __new__(cls, base_dims, derived_dims=(), dimensional_dependencies={}):
|
||||
dimensional_dependencies = dict(dimensional_dependencies)
|
||||
|
||||
def parse_dim(dim):
|
||||
if isinstance(dim, str):
|
||||
dim = Dimension(Symbol(dim))
|
||||
elif isinstance(dim, Dimension):
|
||||
pass
|
||||
elif isinstance(dim, Symbol):
|
||||
dim = Dimension(dim)
|
||||
else:
|
||||
raise TypeError("%s wrong type" % dim)
|
||||
return dim
|
||||
|
||||
base_dims = [parse_dim(i) for i in base_dims]
|
||||
derived_dims = [parse_dim(i) for i in derived_dims]
|
||||
|
||||
for dim in base_dims:
|
||||
if (dim in dimensional_dependencies
|
||||
and (len(dimensional_dependencies[dim]) != 1 or
|
||||
dimensional_dependencies[dim].get(dim, None) != 1)):
|
||||
raise IndexError("Repeated value in base dimensions")
|
||||
dimensional_dependencies[dim] = Dict({dim: 1})
|
||||
|
||||
def parse_dim_name(dim):
|
||||
if isinstance(dim, Dimension):
|
||||
return dim
|
||||
elif isinstance(dim, str):
|
||||
return Dimension(Symbol(dim))
|
||||
elif isinstance(dim, Symbol):
|
||||
return Dimension(dim)
|
||||
else:
|
||||
raise TypeError("unrecognized type %s for %s" % (type(dim), dim))
|
||||
|
||||
for dim in dimensional_dependencies.keys():
|
||||
dim = parse_dim(dim)
|
||||
if (dim not in derived_dims) and (dim not in base_dims):
|
||||
derived_dims.append(dim)
|
||||
|
||||
def parse_dict(d):
|
||||
return Dict({parse_dim_name(i): j for i, j in d.items()})
|
||||
|
||||
# Make sure everything is a SymPy type:
|
||||
dimensional_dependencies = {parse_dim_name(i): parse_dict(j) for i, j in
|
||||
dimensional_dependencies.items()}
|
||||
|
||||
for dim in derived_dims:
|
||||
if dim in base_dims:
|
||||
raise ValueError("Dimension %s both in base and derived" % dim)
|
||||
if dim not in dimensional_dependencies:
|
||||
# TODO: should this raise a warning?
|
||||
dimensional_dependencies[dim] = Dict({dim: 1})
|
||||
|
||||
base_dims.sort(key=default_sort_key)
|
||||
derived_dims.sort(key=default_sort_key)
|
||||
|
||||
base_dims = Tuple(*base_dims)
|
||||
derived_dims = Tuple(*derived_dims)
|
||||
dimensional_dependencies = Dict({i: Dict(j) for i, j in dimensional_dependencies.items()})
|
||||
obj = Basic.__new__(cls, base_dims, derived_dims, dimensional_dependencies)
|
||||
return obj
|
||||
|
||||
@property
|
||||
def base_dims(self):
|
||||
return self.args[0]
|
||||
|
||||
@property
|
||||
def derived_dims(self):
|
||||
return self.args[1]
|
||||
|
||||
@property
|
||||
def dimensional_dependencies(self):
|
||||
return self.args[2]
|
||||
|
||||
def _get_dimensional_dependencies_for_name(self, dimension):
|
||||
if isinstance(dimension, str):
|
||||
dimension = Dimension(Symbol(dimension))
|
||||
elif not isinstance(dimension, Dimension):
|
||||
dimension = Dimension(dimension)
|
||||
|
||||
if dimension.name.is_Symbol:
|
||||
# Dimensions not included in the dependencies are considered
|
||||
# as base dimensions:
|
||||
return dict(self.dimensional_dependencies.get(dimension, {dimension: 1}))
|
||||
|
||||
if dimension.name.is_number or dimension.name.is_NumberSymbol:
|
||||
return {}
|
||||
|
||||
get_for_name = self._get_dimensional_dependencies_for_name
|
||||
|
||||
if dimension.name.is_Mul:
|
||||
ret = collections.defaultdict(int)
|
||||
dicts = [get_for_name(i) for i in dimension.name.args]
|
||||
for d in dicts:
|
||||
for k, v in d.items():
|
||||
ret[k] += v
|
||||
return {k: v for (k, v) in ret.items() if v != 0}
|
||||
|
||||
if dimension.name.is_Add:
|
||||
dicts = [get_for_name(i) for i in dimension.name.args]
|
||||
if all(d == dicts[0] for d in dicts[1:]):
|
||||
return dicts[0]
|
||||
raise TypeError("Only equivalent dimensions can be added or subtracted.")
|
||||
|
||||
if dimension.name.is_Pow:
|
||||
dim_base = get_for_name(dimension.name.base)
|
||||
dim_exp = get_for_name(dimension.name.exp)
|
||||
if dim_exp == {} or dimension.name.exp.is_Symbol:
|
||||
return {k: v * dimension.name.exp for (k, v) in dim_base.items()}
|
||||
else:
|
||||
raise TypeError("The exponent for the power operator must be a Symbol or dimensionless.")
|
||||
|
||||
if dimension.name.is_Function:
|
||||
args = (Dimension._from_dimensional_dependencies(
|
||||
get_for_name(arg)) for arg in dimension.name.args)
|
||||
result = dimension.name.func(*args)
|
||||
|
||||
dicts = [get_for_name(i) for i in dimension.name.args]
|
||||
|
||||
if isinstance(result, Dimension):
|
||||
return self.get_dimensional_dependencies(result)
|
||||
elif result.func == dimension.name.func:
|
||||
if isinstance(dimension.name, TrigonometricFunction):
|
||||
if dicts[0] in ({}, {Dimension('angle'): 1}):
|
||||
return {}
|
||||
else:
|
||||
raise TypeError("The input argument for the function {} must be dimensionless or have dimensions of angle.".format(dimension.func))
|
||||
else:
|
||||
if all(item == {} for item in dicts):
|
||||
return {}
|
||||
else:
|
||||
raise TypeError("The input arguments for the function {} must be dimensionless.".format(dimension.func))
|
||||
else:
|
||||
return get_for_name(result)
|
||||
|
||||
raise TypeError("Type {} not implemented for get_dimensional_dependencies".format(type(dimension.name)))
|
||||
|
||||
def get_dimensional_dependencies(self, name, mark_dimensionless=False):
|
||||
dimdep = self._get_dimensional_dependencies_for_name(name)
|
||||
if mark_dimensionless and dimdep == {}:
|
||||
return {Dimension(1): 1}
|
||||
return dict(dimdep.items())
|
||||
|
||||
def equivalent_dims(self, dim1, dim2):
|
||||
deps1 = self.get_dimensional_dependencies(dim1)
|
||||
deps2 = self.get_dimensional_dependencies(dim2)
|
||||
return deps1 == deps2
|
||||
|
||||
def extend(self, new_base_dims, new_derived_dims=(), new_dim_deps=None):
|
||||
deps = dict(self.dimensional_dependencies)
|
||||
if new_dim_deps:
|
||||
deps.update(new_dim_deps)
|
||||
|
||||
new_dim_sys = DimensionSystem(
|
||||
tuple(self.base_dims) + tuple(new_base_dims),
|
||||
tuple(self.derived_dims) + tuple(new_derived_dims),
|
||||
deps
|
||||
)
|
||||
new_dim_sys._quantity_dimension_map.update(self._quantity_dimension_map)
|
||||
new_dim_sys._quantity_scale_factors.update(self._quantity_scale_factors)
|
||||
return new_dim_sys
|
||||
|
||||
def is_dimensionless(self, dimension):
|
||||
"""
|
||||
Check if the dimension object really has a dimension.
|
||||
|
||||
A dimension should have at least one component with non-zero power.
|
||||
"""
|
||||
if dimension.name == 1:
|
||||
return True
|
||||
return self.get_dimensional_dependencies(dimension) == {}
|
||||
|
||||
@property
|
||||
def list_can_dims(self):
|
||||
"""
|
||||
Useless method, kept for compatibility with previous versions.
|
||||
|
||||
DO NOT USE.
|
||||
|
||||
List all canonical dimension names.
|
||||
"""
|
||||
dimset = set()
|
||||
for i in self.base_dims:
|
||||
dimset.update(set(self.get_dimensional_dependencies(i).keys()))
|
||||
return tuple(sorted(dimset, key=str))
|
||||
|
||||
@property
|
||||
def inv_can_transf_matrix(self):
|
||||
"""
|
||||
Useless method, kept for compatibility with previous versions.
|
||||
|
||||
DO NOT USE.
|
||||
|
||||
Compute the inverse transformation matrix from the base to the
|
||||
canonical dimension basis.
|
||||
|
||||
It corresponds to the matrix where columns are the vector of base
|
||||
dimensions in canonical basis.
|
||||
|
||||
This matrix will almost never be used because dimensions are always
|
||||
defined with respect to the canonical basis, so no work has to be done
|
||||
to get them in this basis. Nonetheless if this matrix is not square
|
||||
(or not invertible) it means that we have chosen a bad basis.
|
||||
"""
|
||||
matrix = reduce(lambda x, y: x.row_join(y),
|
||||
[self.dim_can_vector(d) for d in self.base_dims])
|
||||
return matrix
|
||||
|
||||
@property
|
||||
def can_transf_matrix(self):
|
||||
"""
|
||||
Useless method, kept for compatibility with previous versions.
|
||||
|
||||
DO NOT USE.
|
||||
|
||||
Return the canonical transformation matrix from the canonical to the
|
||||
base dimension basis.
|
||||
|
||||
It is the inverse of the matrix computed with inv_can_transf_matrix().
|
||||
"""
|
||||
|
||||
#TODO: the inversion will fail if the system is inconsistent, for
|
||||
# example if the matrix is not a square
|
||||
return reduce(lambda x, y: x.row_join(y),
|
||||
[self.dim_can_vector(d) for d in sorted(self.base_dims, key=str)]
|
||||
).inv()
|
||||
|
||||
def dim_can_vector(self, dim):
|
||||
"""
|
||||
Useless method, kept for compatibility with previous versions.
|
||||
|
||||
DO NOT USE.
|
||||
|
||||
Dimensional representation in terms of the canonical base dimensions.
|
||||
"""
|
||||
|
||||
vec = []
|
||||
for d in self.list_can_dims:
|
||||
vec.append(self.get_dimensional_dependencies(dim).get(d, 0))
|
||||
return Matrix(vec)
|
||||
|
||||
def dim_vector(self, dim):
|
||||
"""
|
||||
Useless method, kept for compatibility with previous versions.
|
||||
|
||||
DO NOT USE.
|
||||
|
||||
|
||||
Vector representation in terms of the base dimensions.
|
||||
"""
|
||||
return self.can_transf_matrix * Matrix(self.dim_can_vector(dim))
|
||||
|
||||
def print_dim_base(self, dim):
|
||||
"""
|
||||
Give the string expression of a dimension in term of the basis symbols.
|
||||
"""
|
||||
dims = self.dim_vector(dim)
|
||||
symbols = [i.symbol if i.symbol is not None else i.name for i in self.base_dims]
|
||||
res = S.One
|
||||
for (s, p) in zip(symbols, dims):
|
||||
res *= s**p
|
||||
return res
|
||||
|
||||
@property
|
||||
def dim(self):
|
||||
"""
|
||||
Useless method, kept for compatibility with previous versions.
|
||||
|
||||
DO NOT USE.
|
||||
|
||||
Give the dimension of the system.
|
||||
|
||||
That is return the number of dimensions forming the basis.
|
||||
"""
|
||||
return len(self.base_dims)
|
||||
|
||||
@property
|
||||
def is_consistent(self):
|
||||
"""
|
||||
Useless method, kept for compatibility with previous versions.
|
||||
|
||||
DO NOT USE.
|
||||
|
||||
Check if the system is well defined.
|
||||
"""
|
||||
|
||||
# not enough or too many base dimensions compared to independent
|
||||
# dimensions
|
||||
# in vector language: the set of vectors do not form a basis
|
||||
return self.inv_can_transf_matrix.is_square
|
||||
@@ -0,0 +1,219 @@
|
||||
"""
|
||||
Module defining unit prefixe class and some constants.
|
||||
|
||||
Constant dict for SI and binary prefixes are defined as PREFIXES and
|
||||
BIN_PREFIXES.
|
||||
"""
|
||||
from sympy.core.expr import Expr
|
||||
from sympy.core.sympify import sympify
|
||||
from sympy.core.singleton import S
|
||||
|
||||
class Prefix(Expr):
|
||||
"""
|
||||
This class represent prefixes, with their name, symbol and factor.
|
||||
|
||||
Prefixes are used to create derived units from a given unit. They should
|
||||
always be encapsulated into units.
|
||||
|
||||
The factor is constructed from a base (default is 10) to some power, and
|
||||
it gives the total multiple or fraction. For example the kilometer km
|
||||
is constructed from the meter (factor 1) and the kilo (10 to the power 3,
|
||||
i.e. 1000). The base can be changed to allow e.g. binary prefixes.
|
||||
|
||||
A prefix multiplied by something will always return the product of this
|
||||
other object times the factor, except if the other object:
|
||||
|
||||
- is a prefix and they can be combined into a new prefix;
|
||||
- defines multiplication with prefixes (which is the case for the Unit
|
||||
class).
|
||||
"""
|
||||
_op_priority = 13.0
|
||||
is_commutative = True
|
||||
|
||||
def __new__(cls, name, abbrev, exponent, base=sympify(10), latex_repr=None):
|
||||
|
||||
name = sympify(name)
|
||||
abbrev = sympify(abbrev)
|
||||
exponent = sympify(exponent)
|
||||
base = sympify(base)
|
||||
|
||||
obj = Expr.__new__(cls, name, abbrev, exponent, base)
|
||||
obj._name = name
|
||||
obj._abbrev = abbrev
|
||||
obj._scale_factor = base**exponent
|
||||
obj._exponent = exponent
|
||||
obj._base = base
|
||||
obj._latex_repr = latex_repr
|
||||
return obj
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def abbrev(self):
|
||||
return self._abbrev
|
||||
|
||||
@property
|
||||
def scale_factor(self):
|
||||
return self._scale_factor
|
||||
|
||||
def _latex(self, printer):
|
||||
if self._latex_repr is None:
|
||||
return r'\text{%s}' % self._abbrev
|
||||
return self._latex_repr
|
||||
|
||||
@property
|
||||
def base(self):
|
||||
return self._base
|
||||
|
||||
def __str__(self):
|
||||
return str(self._abbrev)
|
||||
|
||||
def __repr__(self):
|
||||
if self.base == 10:
|
||||
return "Prefix(%r, %r, %r)" % (
|
||||
str(self.name), str(self.abbrev), self._exponent)
|
||||
else:
|
||||
return "Prefix(%r, %r, %r, %r)" % (
|
||||
str(self.name), str(self.abbrev), self._exponent, self.base)
|
||||
|
||||
def __mul__(self, other):
|
||||
from sympy.physics.units import Quantity
|
||||
if not isinstance(other, (Quantity, Prefix)):
|
||||
return super().__mul__(other)
|
||||
|
||||
fact = self.scale_factor * other.scale_factor
|
||||
|
||||
if isinstance(other, Prefix):
|
||||
if fact == 1:
|
||||
return S.One
|
||||
# simplify prefix
|
||||
for p in PREFIXES:
|
||||
if PREFIXES[p].scale_factor == fact:
|
||||
return PREFIXES[p]
|
||||
return fact
|
||||
|
||||
return self.scale_factor * other
|
||||
|
||||
def __truediv__(self, other):
|
||||
if not hasattr(other, "scale_factor"):
|
||||
return super().__truediv__(other)
|
||||
|
||||
fact = self.scale_factor / other.scale_factor
|
||||
|
||||
if fact == 1:
|
||||
return S.One
|
||||
elif isinstance(other, Prefix):
|
||||
for p in PREFIXES:
|
||||
if PREFIXES[p].scale_factor == fact:
|
||||
return PREFIXES[p]
|
||||
return fact
|
||||
|
||||
return self.scale_factor / other
|
||||
|
||||
def __rtruediv__(self, other):
|
||||
if other == 1:
|
||||
for p in PREFIXES:
|
||||
if PREFIXES[p].scale_factor == 1 / self.scale_factor:
|
||||
return PREFIXES[p]
|
||||
return other / self.scale_factor
|
||||
|
||||
|
||||
def prefix_unit(unit, prefixes):
|
||||
"""
|
||||
Return a list of all units formed by unit and the given prefixes.
|
||||
|
||||
You can use the predefined PREFIXES or BIN_PREFIXES, but you can also
|
||||
pass as argument a subdict of them if you do not want all prefixed units.
|
||||
|
||||
>>> from sympy.physics.units.prefixes import (PREFIXES,
|
||||
... prefix_unit)
|
||||
>>> from sympy.physics.units import m
|
||||
>>> pref = {"m": PREFIXES["m"], "c": PREFIXES["c"], "d": PREFIXES["d"]}
|
||||
>>> prefix_unit(m, pref) # doctest: +SKIP
|
||||
[millimeter, centimeter, decimeter]
|
||||
"""
|
||||
|
||||
from sympy.physics.units.quantities import Quantity
|
||||
from sympy.physics.units import UnitSystem
|
||||
|
||||
prefixed_units = []
|
||||
|
||||
for prefix in prefixes.values():
|
||||
quantity = Quantity(
|
||||
"%s%s" % (prefix.name, unit.name),
|
||||
abbrev=("%s%s" % (prefix.abbrev, unit.abbrev)),
|
||||
is_prefixed=True,
|
||||
)
|
||||
UnitSystem._quantity_dimensional_equivalence_map_global[quantity] = unit
|
||||
UnitSystem._quantity_scale_factors_global[quantity] = (prefix.scale_factor, unit)
|
||||
prefixed_units.append(quantity)
|
||||
|
||||
return prefixed_units
|
||||
|
||||
|
||||
yotta = Prefix('yotta', 'Y', 24)
|
||||
zetta = Prefix('zetta', 'Z', 21)
|
||||
exa = Prefix('exa', 'E', 18)
|
||||
peta = Prefix('peta', 'P', 15)
|
||||
tera = Prefix('tera', 'T', 12)
|
||||
giga = Prefix('giga', 'G', 9)
|
||||
mega = Prefix('mega', 'M', 6)
|
||||
kilo = Prefix('kilo', 'k', 3)
|
||||
hecto = Prefix('hecto', 'h', 2)
|
||||
deca = Prefix('deca', 'da', 1)
|
||||
deci = Prefix('deci', 'd', -1)
|
||||
centi = Prefix('centi', 'c', -2)
|
||||
milli = Prefix('milli', 'm', -3)
|
||||
micro = Prefix('micro', 'mu', -6, latex_repr=r"\mu")
|
||||
nano = Prefix('nano', 'n', -9)
|
||||
pico = Prefix('pico', 'p', -12)
|
||||
femto = Prefix('femto', 'f', -15)
|
||||
atto = Prefix('atto', 'a', -18)
|
||||
zepto = Prefix('zepto', 'z', -21)
|
||||
yocto = Prefix('yocto', 'y', -24)
|
||||
|
||||
|
||||
# https://physics.nist.gov/cuu/Units/prefixes.html
|
||||
PREFIXES = {
|
||||
'Y': yotta,
|
||||
'Z': zetta,
|
||||
'E': exa,
|
||||
'P': peta,
|
||||
'T': tera,
|
||||
'G': giga,
|
||||
'M': mega,
|
||||
'k': kilo,
|
||||
'h': hecto,
|
||||
'da': deca,
|
||||
'd': deci,
|
||||
'c': centi,
|
||||
'm': milli,
|
||||
'mu': micro,
|
||||
'n': nano,
|
||||
'p': pico,
|
||||
'f': femto,
|
||||
'a': atto,
|
||||
'z': zepto,
|
||||
'y': yocto,
|
||||
}
|
||||
|
||||
|
||||
kibi = Prefix('kibi', 'Y', 10, 2)
|
||||
mebi = Prefix('mebi', 'Y', 20, 2)
|
||||
gibi = Prefix('gibi', 'Y', 30, 2)
|
||||
tebi = Prefix('tebi', 'Y', 40, 2)
|
||||
pebi = Prefix('pebi', 'Y', 50, 2)
|
||||
exbi = Prefix('exbi', 'Y', 60, 2)
|
||||
|
||||
|
||||
# https://physics.nist.gov/cuu/Units/binary.html
|
||||
BIN_PREFIXES = {
|
||||
'Ki': kibi,
|
||||
'Mi': mebi,
|
||||
'Gi': gibi,
|
||||
'Ti': tebi,
|
||||
'Pi': pebi,
|
||||
'Ei': exbi,
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
"""
|
||||
Physical quantities.
|
||||
"""
|
||||
|
||||
from sympy.core.expr import AtomicExpr
|
||||
from sympy.core.symbol import Symbol
|
||||
from sympy.core.sympify import sympify
|
||||
from sympy.physics.units.dimensions import _QuantityMapper
|
||||
from sympy.physics.units.prefixes import Prefix
|
||||
|
||||
|
||||
class Quantity(AtomicExpr):
|
||||
"""
|
||||
Physical quantity: can be a unit of measure, a constant or a generic quantity.
|
||||
"""
|
||||
|
||||
is_commutative = True
|
||||
is_real = True
|
||||
is_number = False
|
||||
is_nonzero = True
|
||||
is_physical_constant = False
|
||||
_diff_wrt = True
|
||||
|
||||
def __new__(cls, name, abbrev=None,
|
||||
latex_repr=None, pretty_unicode_repr=None,
|
||||
pretty_ascii_repr=None, mathml_presentation_repr=None,
|
||||
is_prefixed=False,
|
||||
**assumptions):
|
||||
|
||||
if not isinstance(name, Symbol):
|
||||
name = Symbol(name)
|
||||
|
||||
if abbrev is None:
|
||||
abbrev = name
|
||||
elif isinstance(abbrev, str):
|
||||
abbrev = Symbol(abbrev)
|
||||
|
||||
# HACK: These are here purely for type checking. They actually get assigned below.
|
||||
cls._is_prefixed = is_prefixed
|
||||
|
||||
obj = AtomicExpr.__new__(cls, name, abbrev)
|
||||
obj._name = name
|
||||
obj._abbrev = abbrev
|
||||
obj._latex_repr = latex_repr
|
||||
obj._unicode_repr = pretty_unicode_repr
|
||||
obj._ascii_repr = pretty_ascii_repr
|
||||
obj._mathml_repr = mathml_presentation_repr
|
||||
obj._is_prefixed = is_prefixed
|
||||
return obj
|
||||
|
||||
def set_global_dimension(self, dimension):
|
||||
_QuantityMapper._quantity_dimension_global[self] = dimension
|
||||
|
||||
def set_global_relative_scale_factor(self, scale_factor, reference_quantity):
|
||||
"""
|
||||
Setting a scale factor that is valid across all unit system.
|
||||
"""
|
||||
from sympy.physics.units import UnitSystem
|
||||
scale_factor = sympify(scale_factor)
|
||||
if isinstance(scale_factor, Prefix):
|
||||
self._is_prefixed = True
|
||||
# replace all prefixes by their ratio to canonical units:
|
||||
scale_factor = scale_factor.replace(
|
||||
lambda x: isinstance(x, Prefix),
|
||||
lambda x: x.scale_factor
|
||||
)
|
||||
scale_factor = sympify(scale_factor)
|
||||
UnitSystem._quantity_scale_factors_global[self] = (scale_factor, reference_quantity)
|
||||
UnitSystem._quantity_dimensional_equivalence_map_global[self] = reference_quantity
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def dimension(self):
|
||||
from sympy.physics.units import UnitSystem
|
||||
unit_system = UnitSystem.get_default_unit_system()
|
||||
return unit_system.get_quantity_dimension(self)
|
||||
|
||||
@property
|
||||
def abbrev(self):
|
||||
"""
|
||||
Symbol representing the unit name.
|
||||
|
||||
Prepend the abbreviation with the prefix symbol if it is defines.
|
||||
"""
|
||||
return self._abbrev
|
||||
|
||||
@property
|
||||
def scale_factor(self):
|
||||
"""
|
||||
Overall magnitude of the quantity as compared to the canonical units.
|
||||
"""
|
||||
from sympy.physics.units import UnitSystem
|
||||
unit_system = UnitSystem.get_default_unit_system()
|
||||
return unit_system.get_quantity_scale_factor(self)
|
||||
|
||||
def _eval_is_positive(self):
|
||||
return True
|
||||
|
||||
def _eval_is_constant(self):
|
||||
return True
|
||||
|
||||
def _eval_Abs(self):
|
||||
return self
|
||||
|
||||
def _eval_subs(self, old, new):
|
||||
if isinstance(new, Quantity) and self != old:
|
||||
return self
|
||||
|
||||
def _latex(self, printer):
|
||||
if self._latex_repr:
|
||||
return self._latex_repr
|
||||
else:
|
||||
return r'\text{{{}}}'.format(self.args[1] \
|
||||
if len(self.args) >= 2 else self.args[0])
|
||||
|
||||
def convert_to(self, other, unit_system="SI"):
|
||||
"""
|
||||
Convert the quantity to another quantity of same dimensions.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy.physics.units import speed_of_light, meter, second
|
||||
>>> speed_of_light
|
||||
speed_of_light
|
||||
>>> speed_of_light.convert_to(meter/second)
|
||||
299792458*meter/second
|
||||
|
||||
>>> from sympy.physics.units import liter
|
||||
>>> liter.convert_to(meter**3)
|
||||
meter**3/1000
|
||||
"""
|
||||
from .util import convert_to
|
||||
return convert_to(self, other, unit_system)
|
||||
|
||||
@property
|
||||
def free_symbols(self):
|
||||
"""Return free symbols from quantity."""
|
||||
return set()
|
||||
|
||||
@property
|
||||
def is_prefixed(self):
|
||||
"""Whether or not the quantity is prefixed. Eg. `kilogram` is prefixed, but `gram` is not."""
|
||||
return self._is_prefixed
|
||||
|
||||
class PhysicalConstant(Quantity):
|
||||
"""Represents a physical constant, eg. `speed_of_light` or `avogadro_constant`."""
|
||||
|
||||
is_physical_constant = True
|
||||
@@ -0,0 +1,6 @@
|
||||
from sympy.physics.units.systems.mks import MKS
|
||||
from sympy.physics.units.systems.mksa import MKSA
|
||||
from sympy.physics.units.systems.natural import natural
|
||||
from sympy.physics.units.systems.si import SI
|
||||
|
||||
__all__ = ['MKS', 'MKSA', 'natural', 'SI']
|
||||
@@ -0,0 +1,82 @@
|
||||
from sympy.core.singleton import S
|
||||
from sympy.functions.elementary.miscellaneous import sqrt
|
||||
from sympy.physics.units import UnitSystem, centimeter, gram, second, coulomb, charge, speed_of_light, current, mass, \
|
||||
length, voltage, magnetic_density, magnetic_flux
|
||||
from sympy.physics.units.definitions import coulombs_constant
|
||||
from sympy.physics.units.definitions.unit_definitions import statcoulomb, statampere, statvolt, volt, tesla, gauss, \
|
||||
weber, maxwell, debye, oersted, ohm, farad, henry, erg, ampere, coulomb_constant
|
||||
from sympy.physics.units.systems.mks import dimsys_length_weight_time
|
||||
|
||||
One = S.One
|
||||
|
||||
dimsys_cgs = dimsys_length_weight_time.extend(
|
||||
[],
|
||||
new_dim_deps={
|
||||
# Dimensional dependencies for derived dimensions
|
||||
"impedance": {"time": 1, "length": -1},
|
||||
"conductance": {"time": -1, "length": 1},
|
||||
"capacitance": {"length": 1},
|
||||
"inductance": {"time": 2, "length": -1},
|
||||
"charge": {"mass": S.Half, "length": S(3)/2, "time": -1},
|
||||
"current": {"mass": One/2, "length": 3*One/2, "time": -2},
|
||||
"voltage": {"length": -One/2, "mass": One/2, "time": -1},
|
||||
"magnetic_density": {"length": -One/2, "mass": One/2, "time": -1},
|
||||
"magnetic_flux": {"length": 3*One/2, "mass": One/2, "time": -1},
|
||||
}
|
||||
)
|
||||
|
||||
cgs_gauss = UnitSystem(
|
||||
base_units=[centimeter, gram, second],
|
||||
units=[],
|
||||
name="cgs_gauss",
|
||||
dimension_system=dimsys_cgs)
|
||||
|
||||
|
||||
cgs_gauss.set_quantity_scale_factor(coulombs_constant, 1)
|
||||
|
||||
cgs_gauss.set_quantity_dimension(statcoulomb, charge)
|
||||
cgs_gauss.set_quantity_scale_factor(statcoulomb, centimeter**(S(3)/2)*gram**(S.Half)/second)
|
||||
|
||||
cgs_gauss.set_quantity_dimension(coulomb, charge)
|
||||
|
||||
cgs_gauss.set_quantity_dimension(statampere, current)
|
||||
cgs_gauss.set_quantity_scale_factor(statampere, statcoulomb/second)
|
||||
|
||||
cgs_gauss.set_quantity_dimension(statvolt, voltage)
|
||||
cgs_gauss.set_quantity_scale_factor(statvolt, erg/statcoulomb)
|
||||
|
||||
cgs_gauss.set_quantity_dimension(volt, voltage)
|
||||
|
||||
cgs_gauss.set_quantity_dimension(gauss, magnetic_density)
|
||||
cgs_gauss.set_quantity_scale_factor(gauss, sqrt(gram/centimeter)/second)
|
||||
|
||||
cgs_gauss.set_quantity_dimension(tesla, magnetic_density)
|
||||
|
||||
cgs_gauss.set_quantity_dimension(maxwell, magnetic_flux)
|
||||
cgs_gauss.set_quantity_scale_factor(maxwell, sqrt(centimeter**3*gram)/second)
|
||||
|
||||
# SI units expressed in CGS-gaussian units:
|
||||
cgs_gauss.set_quantity_scale_factor(coulomb, 10*speed_of_light*statcoulomb)
|
||||
cgs_gauss.set_quantity_scale_factor(ampere, 10*speed_of_light*statcoulomb/second)
|
||||
cgs_gauss.set_quantity_scale_factor(volt, 10**6/speed_of_light*statvolt)
|
||||
cgs_gauss.set_quantity_scale_factor(weber, 10**8*maxwell)
|
||||
cgs_gauss.set_quantity_scale_factor(tesla, 10**4*gauss)
|
||||
cgs_gauss.set_quantity_scale_factor(debye, One/10**18*statcoulomb*centimeter)
|
||||
cgs_gauss.set_quantity_scale_factor(oersted, sqrt(gram/centimeter)/second)
|
||||
cgs_gauss.set_quantity_scale_factor(ohm, 10**5/speed_of_light**2*second/centimeter)
|
||||
cgs_gauss.set_quantity_scale_factor(farad, One/10**5*speed_of_light**2*centimeter)
|
||||
cgs_gauss.set_quantity_scale_factor(henry, 10**5/speed_of_light**2/centimeter*second**2)
|
||||
|
||||
# Coulomb's constant:
|
||||
cgs_gauss.set_quantity_dimension(coulomb_constant, 1)
|
||||
cgs_gauss.set_quantity_scale_factor(coulomb_constant, 1)
|
||||
|
||||
__all__ = [
|
||||
'ohm', 'tesla', 'maxwell', 'speed_of_light', 'volt', 'second', 'voltage',
|
||||
'debye', 'dimsys_length_weight_time', 'centimeter', 'coulomb_constant',
|
||||
'farad', 'sqrt', 'UnitSystem', 'current', 'charge', 'weber', 'gram',
|
||||
'statcoulomb', 'gauss', 'S', 'statvolt', 'oersted', 'statampere',
|
||||
'dimsys_cgs', 'coulomb', 'magnetic_density', 'magnetic_flux', 'One',
|
||||
'length', 'erg', 'mass', 'coulombs_constant', 'henry', 'ampere',
|
||||
'cgs_gauss',
|
||||
]
|
||||
@@ -0,0 +1,156 @@
|
||||
from sympy.core.singleton import S
|
||||
|
||||
from sympy.core.numbers import pi
|
||||
|
||||
from sympy.physics.units import DimensionSystem, hertz, kilogram
|
||||
from sympy.physics.units.definitions import (
|
||||
G, Hz, J, N, Pa, W, c, g, kg, m, s, meter, gram, second, newton,
|
||||
joule, watt, pascal)
|
||||
from sympy.physics.units.definitions.dimension_definitions import (
|
||||
acceleration, action, energy, force, frequency, momentum,
|
||||
power, pressure, velocity, length, mass, time)
|
||||
from sympy.physics.units.prefixes import PREFIXES, prefix_unit
|
||||
from sympy.physics.units.prefixes import (
|
||||
kibi, mebi, gibi, tebi, pebi, exbi
|
||||
)
|
||||
from sympy.physics.units.definitions import (
|
||||
cd, K, coulomb, volt, ohm, siemens, farad, henry, tesla, weber, dioptre,
|
||||
lux, katal, gray, becquerel, inch, hectare, liter, julian_year,
|
||||
gravitational_constant, speed_of_light, elementary_charge, planck, hbar,
|
||||
electronvolt, avogadro_number, avogadro_constant, boltzmann_constant,
|
||||
stefan_boltzmann_constant, atomic_mass_constant, molar_gas_constant,
|
||||
faraday_constant, josephson_constant, von_klitzing_constant,
|
||||
acceleration_due_to_gravity, magnetic_constant, vacuum_permittivity,
|
||||
vacuum_impedance, coulomb_constant, atmosphere, bar, pound, psi, mmHg,
|
||||
milli_mass_unit, quart, lightyear, astronomical_unit, planck_mass,
|
||||
planck_time, planck_temperature, planck_length, planck_charge,
|
||||
planck_area, planck_volume, planck_momentum, planck_energy, planck_force,
|
||||
planck_power, planck_density, planck_energy_density, planck_intensity,
|
||||
planck_angular_frequency, planck_pressure, planck_current, planck_voltage,
|
||||
planck_impedance, planck_acceleration, bit, byte, kibibyte, mebibyte,
|
||||
gibibyte, tebibyte, pebibyte, exbibyte, curie, rutherford, radian, degree,
|
||||
steradian, angular_mil, atomic_mass_unit, gee, kPa, ampere, u0, kelvin,
|
||||
mol, mole, candela, electric_constant, boltzmann, angstrom
|
||||
)
|
||||
|
||||
|
||||
dimsys_length_weight_time = DimensionSystem([
|
||||
# Dimensional dependencies for MKS base dimensions
|
||||
length,
|
||||
mass,
|
||||
time,
|
||||
], dimensional_dependencies={
|
||||
# Dimensional dependencies for derived dimensions
|
||||
"velocity": {"length": 1, "time": -1},
|
||||
"acceleration": {"length": 1, "time": -2},
|
||||
"momentum": {"mass": 1, "length": 1, "time": -1},
|
||||
"force": {"mass": 1, "length": 1, "time": -2},
|
||||
"energy": {"mass": 1, "length": 2, "time": -2},
|
||||
"power": {"length": 2, "mass": 1, "time": -3},
|
||||
"pressure": {"mass": 1, "length": -1, "time": -2},
|
||||
"frequency": {"time": -1},
|
||||
"action": {"length": 2, "mass": 1, "time": -1},
|
||||
"area": {"length": 2},
|
||||
"volume": {"length": 3},
|
||||
})
|
||||
|
||||
|
||||
One = S.One
|
||||
|
||||
|
||||
# Base units:
|
||||
dimsys_length_weight_time.set_quantity_dimension(meter, length)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(meter, One)
|
||||
|
||||
# gram; used to define its prefixed units
|
||||
dimsys_length_weight_time.set_quantity_dimension(gram, mass)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(gram, One)
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(second, time)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(second, One)
|
||||
|
||||
# derived units
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(newton, force)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(newton, kilogram*meter/second**2)
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(joule, energy)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(joule, newton*meter)
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(watt, power)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(watt, joule/second)
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(pascal, pressure)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(pascal, newton/meter**2)
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(hertz, frequency)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(hertz, One)
|
||||
|
||||
# Other derived units:
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(dioptre, 1 / length)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(dioptre, 1/meter)
|
||||
|
||||
# Common volume and area units
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(hectare, length**2)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(hectare, (meter**2)*(10000))
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(liter, length**3)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(liter, meter**3/1000)
|
||||
|
||||
|
||||
# Newton constant
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(gravitational_constant, length ** 3 * mass ** -1 * time ** -2)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(gravitational_constant, 6.67430e-11*m**3/(kg*s**2))
|
||||
|
||||
# speed of light
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(speed_of_light, velocity)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(speed_of_light, 299792458*meter/second)
|
||||
|
||||
|
||||
# Planck constant
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(planck, action)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(planck, 6.62607015e-34*joule*second)
|
||||
|
||||
# Reduced Planck constant
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
dimsys_length_weight_time.set_quantity_dimension(hbar, action)
|
||||
dimsys_length_weight_time.set_quantity_scale_factor(hbar, planck / (2 * pi))
|
||||
|
||||
|
||||
__all__ = [
|
||||
'mmHg', 'atmosphere', 'newton', 'meter', 'vacuum_permittivity', 'pascal',
|
||||
'magnetic_constant', 'angular_mil', 'julian_year', 'weber', 'exbibyte',
|
||||
'liter', 'molar_gas_constant', 'faraday_constant', 'avogadro_constant',
|
||||
'planck_momentum', 'planck_density', 'gee', 'mol', 'bit', 'gray', 'kibi',
|
||||
'bar', 'curie', 'prefix_unit', 'PREFIXES', 'planck_time', 'gram',
|
||||
'candela', 'force', 'planck_intensity', 'energy', 'becquerel',
|
||||
'planck_acceleration', 'speed_of_light', 'dioptre', 'second', 'frequency',
|
||||
'Hz', 'power', 'lux', 'planck_current', 'momentum', 'tebibyte',
|
||||
'planck_power', 'degree', 'mebi', 'K', 'planck_volume',
|
||||
'quart', 'pressure', 'W', 'joule', 'boltzmann_constant', 'c', 'g',
|
||||
'planck_force', 'exbi', 's', 'watt', 'action', 'hbar', 'gibibyte',
|
||||
'DimensionSystem', 'cd', 'volt', 'planck_charge', 'angstrom',
|
||||
'dimsys_length_weight_time', 'pebi', 'vacuum_impedance', 'planck',
|
||||
'farad', 'gravitational_constant', 'u0', 'hertz', 'tesla', 'steradian',
|
||||
'josephson_constant', 'planck_area', 'stefan_boltzmann_constant',
|
||||
'astronomical_unit', 'J', 'N', 'planck_voltage', 'planck_energy',
|
||||
'atomic_mass_constant', 'rutherford', 'elementary_charge', 'Pa',
|
||||
'planck_mass', 'henry', 'planck_angular_frequency', 'ohm', 'pound',
|
||||
'planck_pressure', 'G', 'avogadro_number', 'psi', 'von_klitzing_constant',
|
||||
'planck_length', 'radian', 'mole', 'acceleration',
|
||||
'planck_energy_density', 'mebibyte', 'length',
|
||||
'acceleration_due_to_gravity', 'planck_temperature', 'tebi', 'inch',
|
||||
'electronvolt', 'coulomb_constant', 'kelvin', 'kPa', 'boltzmann',
|
||||
'milli_mass_unit', 'gibi', 'planck_impedance', 'electric_constant', 'kg',
|
||||
'coulomb', 'siemens', 'byte', 'atomic_mass_unit', 'm', 'kibibyte',
|
||||
'kilogram', 'lightyear', 'mass', 'time', 'pebibyte', 'velocity',
|
||||
'ampere', 'katal',
|
||||
]
|
||||
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
MKS unit system.
|
||||
|
||||
MKS stands for "meter, kilogram, second".
|
||||
"""
|
||||
|
||||
from sympy.physics.units import UnitSystem
|
||||
from sympy.physics.units.definitions import gravitational_constant, hertz, joule, newton, pascal, watt, speed_of_light, gram, kilogram, meter, second
|
||||
from sympy.physics.units.definitions.dimension_definitions import (
|
||||
acceleration, action, energy, force, frequency, momentum,
|
||||
power, pressure, velocity, length, mass, time)
|
||||
from sympy.physics.units.prefixes import PREFIXES, prefix_unit
|
||||
from sympy.physics.units.systems.length_weight_time import dimsys_length_weight_time
|
||||
|
||||
dims = (velocity, acceleration, momentum, force, energy, power, pressure,
|
||||
frequency, action)
|
||||
|
||||
units = [meter, gram, second, joule, newton, watt, pascal, hertz]
|
||||
all_units = []
|
||||
|
||||
# Prefixes of units like gram, joule, newton etc get added using `prefix_unit`
|
||||
# in the for loop, but the actual units have to be added manually.
|
||||
all_units.extend([gram, joule, newton, watt, pascal, hertz])
|
||||
|
||||
for u in units:
|
||||
all_units.extend(prefix_unit(u, PREFIXES))
|
||||
all_units.extend([gravitational_constant, speed_of_light])
|
||||
|
||||
# unit system
|
||||
MKS = UnitSystem(base_units=(meter, kilogram, second), units=all_units, name="MKS", dimension_system=dimsys_length_weight_time, derived_units={
|
||||
power: watt,
|
||||
time: second,
|
||||
pressure: pascal,
|
||||
length: meter,
|
||||
frequency: hertz,
|
||||
mass: kilogram,
|
||||
force: newton,
|
||||
energy: joule,
|
||||
velocity: meter/second,
|
||||
acceleration: meter/(second**2),
|
||||
})
|
||||
|
||||
|
||||
__all__ = [
|
||||
'MKS', 'units', 'all_units', 'dims',
|
||||
]
|
||||
@@ -0,0 +1,54 @@
|
||||
"""
|
||||
MKS unit system.
|
||||
|
||||
MKS stands for "meter, kilogram, second, ampere".
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from sympy.physics.units.definitions import Z0, ampere, coulomb, farad, henry, siemens, tesla, volt, weber, ohm
|
||||
from sympy.physics.units.definitions.dimension_definitions import (
|
||||
capacitance, charge, conductance, current, impedance, inductance,
|
||||
magnetic_density, magnetic_flux, voltage)
|
||||
from sympy.physics.units.prefixes import PREFIXES, prefix_unit
|
||||
from sympy.physics.units.systems.mks import MKS, dimsys_length_weight_time
|
||||
from sympy.physics.units.quantities import Quantity
|
||||
|
||||
dims = (voltage, impedance, conductance, current, capacitance, inductance, charge,
|
||||
magnetic_density, magnetic_flux)
|
||||
|
||||
units = [ampere, volt, ohm, siemens, farad, henry, coulomb, tesla, weber]
|
||||
|
||||
all_units: list[Quantity] = []
|
||||
for u in units:
|
||||
all_units.extend(prefix_unit(u, PREFIXES))
|
||||
all_units.extend(units)
|
||||
|
||||
all_units.append(Z0)
|
||||
|
||||
dimsys_MKSA = dimsys_length_weight_time.extend([
|
||||
# Dimensional dependencies for base dimensions (MKSA not in MKS)
|
||||
current,
|
||||
], new_dim_deps={
|
||||
# Dimensional dependencies for derived dimensions
|
||||
"voltage": {"mass": 1, "length": 2, "current": -1, "time": -3},
|
||||
"impedance": {"mass": 1, "length": 2, "current": -2, "time": -3},
|
||||
"conductance": {"mass": -1, "length": -2, "current": 2, "time": 3},
|
||||
"capacitance": {"mass": -1, "length": -2, "current": 2, "time": 4},
|
||||
"inductance": {"mass": 1, "length": 2, "current": -2, "time": -2},
|
||||
"charge": {"current": 1, "time": 1},
|
||||
"magnetic_density": {"mass": 1, "current": -1, "time": -2},
|
||||
"magnetic_flux": {"length": 2, "mass": 1, "current": -1, "time": -2},
|
||||
})
|
||||
|
||||
MKSA = MKS.extend(base=(ampere,), units=all_units, name='MKSA', dimension_system=dimsys_MKSA, derived_units={
|
||||
magnetic_flux: weber,
|
||||
impedance: ohm,
|
||||
current: ampere,
|
||||
voltage: volt,
|
||||
inductance: henry,
|
||||
conductance: siemens,
|
||||
magnetic_density: tesla,
|
||||
charge: coulomb,
|
||||
capacitance: farad,
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
Naturalunit system.
|
||||
|
||||
The natural system comes from "setting c = 1, hbar = 1". From the computer
|
||||
point of view it means that we use velocity and action instead of length and
|
||||
time. Moreover instead of mass we use energy.
|
||||
"""
|
||||
|
||||
from sympy.physics.units import DimensionSystem
|
||||
from sympy.physics.units.definitions import c, eV, hbar
|
||||
from sympy.physics.units.definitions.dimension_definitions import (
|
||||
action, energy, force, frequency, length, mass, momentum,
|
||||
power, time, velocity)
|
||||
from sympy.physics.units.prefixes import PREFIXES, prefix_unit
|
||||
from sympy.physics.units.unitsystem import UnitSystem
|
||||
|
||||
|
||||
# dimension system
|
||||
_natural_dim = DimensionSystem(
|
||||
base_dims=(action, energy, velocity),
|
||||
derived_dims=(length, mass, time, momentum, force, power, frequency)
|
||||
)
|
||||
|
||||
units = prefix_unit(eV, PREFIXES)
|
||||
|
||||
# unit system
|
||||
natural = UnitSystem(base_units=(hbar, eV, c), units=units, name="Natural system")
|
||||
@@ -0,0 +1,377 @@
|
||||
"""
|
||||
SI unit system.
|
||||
Based on MKSA, which stands for "meter, kilogram, second, ampere".
|
||||
Added kelvin, candela and mole.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from sympy.physics.units import DimensionSystem, Dimension, dHg0
|
||||
|
||||
from sympy.physics.units.quantities import Quantity
|
||||
|
||||
from sympy.core.numbers import (Rational, pi)
|
||||
from sympy.core.singleton import S
|
||||
from sympy.functions.elementary.miscellaneous import sqrt
|
||||
from sympy.physics.units.definitions.dimension_definitions import (
|
||||
acceleration, action, current, impedance, length, mass, time, velocity,
|
||||
amount_of_substance, temperature, information, frequency, force, pressure,
|
||||
energy, power, charge, voltage, capacitance, conductance, magnetic_flux,
|
||||
magnetic_density, inductance, luminous_intensity
|
||||
)
|
||||
from sympy.physics.units.definitions import (
|
||||
kilogram, newton, second, meter, gram, cd, K, joule, watt, pascal, hertz,
|
||||
coulomb, volt, ohm, siemens, farad, henry, tesla, weber, dioptre, lux,
|
||||
katal, gray, becquerel, inch, liter, julian_year, gravitational_constant,
|
||||
speed_of_light, elementary_charge, planck, hbar, electronvolt,
|
||||
avogadro_number, avogadro_constant, boltzmann_constant, electron_rest_mass,
|
||||
stefan_boltzmann_constant, Da, atomic_mass_constant, molar_gas_constant,
|
||||
faraday_constant, josephson_constant, von_klitzing_constant,
|
||||
acceleration_due_to_gravity, magnetic_constant, vacuum_permittivity,
|
||||
vacuum_impedance, coulomb_constant, atmosphere, bar, pound, psi, mmHg,
|
||||
milli_mass_unit, quart, lightyear, astronomical_unit, planck_mass,
|
||||
planck_time, planck_temperature, planck_length, planck_charge, planck_area,
|
||||
planck_volume, planck_momentum, planck_energy, planck_force, planck_power,
|
||||
planck_density, planck_energy_density, planck_intensity,
|
||||
planck_angular_frequency, planck_pressure, planck_current, planck_voltage,
|
||||
planck_impedance, planck_acceleration, bit, byte, kibibyte, mebibyte,
|
||||
gibibyte, tebibyte, pebibyte, exbibyte, curie, rutherford, radian, degree,
|
||||
steradian, angular_mil, atomic_mass_unit, gee, kPa, ampere, u0, c, kelvin,
|
||||
mol, mole, candela, m, kg, s, electric_constant, G, boltzmann
|
||||
)
|
||||
from sympy.physics.units.prefixes import PREFIXES, prefix_unit
|
||||
from sympy.physics.units.systems.mksa import MKSA, dimsys_MKSA
|
||||
|
||||
derived_dims = (frequency, force, pressure, energy, power, charge, voltage,
|
||||
capacitance, conductance, magnetic_flux,
|
||||
magnetic_density, inductance, luminous_intensity)
|
||||
base_dims = (amount_of_substance, luminous_intensity, temperature)
|
||||
|
||||
units = [mol, cd, K, lux, hertz, newton, pascal, joule, watt, coulomb, volt,
|
||||
farad, ohm, siemens, weber, tesla, henry, candela, lux, becquerel,
|
||||
gray, katal]
|
||||
|
||||
all_units: list[Quantity] = []
|
||||
for u in units:
|
||||
all_units.extend(prefix_unit(u, PREFIXES))
|
||||
|
||||
all_units.extend(units)
|
||||
all_units.extend([mol, cd, K, lux])
|
||||
|
||||
|
||||
dimsys_SI = dimsys_MKSA.extend(
|
||||
[
|
||||
# Dimensional dependencies for other base dimensions:
|
||||
temperature,
|
||||
amount_of_substance,
|
||||
luminous_intensity,
|
||||
])
|
||||
|
||||
dimsys_default = dimsys_SI.extend(
|
||||
[information],
|
||||
)
|
||||
|
||||
SI = MKSA.extend(base=(mol, cd, K), units=all_units, name='SI', dimension_system=dimsys_SI, derived_units={
|
||||
power: watt,
|
||||
magnetic_flux: weber,
|
||||
time: second,
|
||||
impedance: ohm,
|
||||
pressure: pascal,
|
||||
current: ampere,
|
||||
voltage: volt,
|
||||
length: meter,
|
||||
frequency: hertz,
|
||||
inductance: henry,
|
||||
temperature: kelvin,
|
||||
amount_of_substance: mole,
|
||||
luminous_intensity: candela,
|
||||
conductance: siemens,
|
||||
mass: kilogram,
|
||||
magnetic_density: tesla,
|
||||
charge: coulomb,
|
||||
force: newton,
|
||||
capacitance: farad,
|
||||
energy: joule,
|
||||
velocity: meter/second,
|
||||
})
|
||||
|
||||
One = S.One
|
||||
|
||||
SI.set_quantity_dimension(radian, One)
|
||||
|
||||
SI.set_quantity_scale_factor(ampere, One)
|
||||
|
||||
SI.set_quantity_scale_factor(kelvin, One)
|
||||
|
||||
SI.set_quantity_scale_factor(mole, One)
|
||||
|
||||
SI.set_quantity_scale_factor(candela, One)
|
||||
|
||||
# MKSA extension to MKS: derived units
|
||||
|
||||
SI.set_quantity_scale_factor(coulomb, One)
|
||||
|
||||
SI.set_quantity_scale_factor(volt, joule/coulomb)
|
||||
|
||||
SI.set_quantity_scale_factor(ohm, volt/ampere)
|
||||
|
||||
SI.set_quantity_scale_factor(siemens, ampere/volt)
|
||||
|
||||
SI.set_quantity_scale_factor(farad, coulomb/volt)
|
||||
|
||||
SI.set_quantity_scale_factor(henry, volt*second/ampere)
|
||||
|
||||
SI.set_quantity_scale_factor(tesla, volt*second/meter**2)
|
||||
|
||||
SI.set_quantity_scale_factor(weber, joule/ampere)
|
||||
|
||||
|
||||
SI.set_quantity_dimension(lux, luminous_intensity / length ** 2)
|
||||
SI.set_quantity_scale_factor(lux, steradian*candela/meter**2)
|
||||
|
||||
# katal is the SI unit of catalytic activity
|
||||
|
||||
SI.set_quantity_dimension(katal, amount_of_substance / time)
|
||||
SI.set_quantity_scale_factor(katal, mol/second)
|
||||
|
||||
# gray is the SI unit of absorbed dose
|
||||
|
||||
SI.set_quantity_dimension(gray, energy / mass)
|
||||
SI.set_quantity_scale_factor(gray, meter**2/second**2)
|
||||
|
||||
# becquerel is the SI unit of radioactivity
|
||||
|
||||
SI.set_quantity_dimension(becquerel, 1 / time)
|
||||
SI.set_quantity_scale_factor(becquerel, 1/second)
|
||||
|
||||
#### CONSTANTS ####
|
||||
|
||||
# elementary charge
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
SI.set_quantity_dimension(elementary_charge, charge)
|
||||
SI.set_quantity_scale_factor(elementary_charge, 1.602176634e-19*coulomb)
|
||||
|
||||
# Electronvolt
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
SI.set_quantity_dimension(electronvolt, energy)
|
||||
SI.set_quantity_scale_factor(electronvolt, 1.602176634e-19*joule)
|
||||
|
||||
# Avogadro number
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
SI.set_quantity_dimension(avogadro_number, One)
|
||||
SI.set_quantity_scale_factor(avogadro_number, 6.02214076e23)
|
||||
|
||||
# Avogadro constant
|
||||
|
||||
SI.set_quantity_dimension(avogadro_constant, amount_of_substance ** -1)
|
||||
SI.set_quantity_scale_factor(avogadro_constant, avogadro_number / mol)
|
||||
|
||||
# Boltzmann constant
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
SI.set_quantity_dimension(boltzmann_constant, energy / temperature)
|
||||
SI.set_quantity_scale_factor(boltzmann_constant, 1.380649e-23*joule/kelvin)
|
||||
|
||||
# Stefan-Boltzmann constant
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
SI.set_quantity_dimension(stefan_boltzmann_constant, energy * time ** -1 * length ** -2 * temperature ** -4)
|
||||
SI.set_quantity_scale_factor(stefan_boltzmann_constant, pi**2 * boltzmann_constant**4 / (60 * hbar**3 * speed_of_light ** 2))
|
||||
|
||||
# Atomic mass
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
SI.set_quantity_dimension(atomic_mass_constant, mass)
|
||||
SI.set_quantity_scale_factor(atomic_mass_constant, 1.66053906660e-24*gram)
|
||||
|
||||
# Molar gas constant
|
||||
# REF: NIST SP 959 (June 2019)
|
||||
|
||||
SI.set_quantity_dimension(molar_gas_constant, energy / (temperature * amount_of_substance))
|
||||
SI.set_quantity_scale_factor(molar_gas_constant, boltzmann_constant * avogadro_constant)
|
||||
|
||||
# Faraday constant
|
||||
|
||||
SI.set_quantity_dimension(faraday_constant, charge / amount_of_substance)
|
||||
SI.set_quantity_scale_factor(faraday_constant, elementary_charge * avogadro_constant)
|
||||
|
||||
# Josephson constant
|
||||
|
||||
SI.set_quantity_dimension(josephson_constant, frequency / voltage)
|
||||
SI.set_quantity_scale_factor(josephson_constant, 0.5 * planck / elementary_charge)
|
||||
|
||||
# Von Klitzing constant
|
||||
|
||||
SI.set_quantity_dimension(von_klitzing_constant, voltage / current)
|
||||
SI.set_quantity_scale_factor(von_klitzing_constant, hbar / elementary_charge ** 2)
|
||||
|
||||
# Acceleration due to gravity (on the Earth surface)
|
||||
|
||||
SI.set_quantity_dimension(acceleration_due_to_gravity, acceleration)
|
||||
SI.set_quantity_scale_factor(acceleration_due_to_gravity, 9.80665*meter/second**2)
|
||||
|
||||
# magnetic constant:
|
||||
|
||||
SI.set_quantity_dimension(magnetic_constant, force / current ** 2)
|
||||
SI.set_quantity_scale_factor(magnetic_constant, 4*pi/10**7 * newton/ampere**2)
|
||||
|
||||
# electric constant:
|
||||
|
||||
SI.set_quantity_dimension(vacuum_permittivity, capacitance / length)
|
||||
SI.set_quantity_scale_factor(vacuum_permittivity, 1/(u0 * c**2))
|
||||
|
||||
# vacuum impedance:
|
||||
|
||||
SI.set_quantity_dimension(vacuum_impedance, impedance)
|
||||
SI.set_quantity_scale_factor(vacuum_impedance, u0 * c)
|
||||
|
||||
# Electron rest mass
|
||||
SI.set_quantity_dimension(electron_rest_mass, mass)
|
||||
SI.set_quantity_scale_factor(electron_rest_mass, 9.1093837015e-31*kilogram)
|
||||
|
||||
# Coulomb's constant:
|
||||
SI.set_quantity_dimension(coulomb_constant, force * length ** 2 / charge ** 2)
|
||||
SI.set_quantity_scale_factor(coulomb_constant, 1/(4*pi*vacuum_permittivity))
|
||||
|
||||
SI.set_quantity_dimension(psi, pressure)
|
||||
SI.set_quantity_scale_factor(psi, pound * gee / inch ** 2)
|
||||
|
||||
SI.set_quantity_dimension(mmHg, pressure)
|
||||
SI.set_quantity_scale_factor(mmHg, dHg0 * acceleration_due_to_gravity * kilogram / meter**2)
|
||||
|
||||
SI.set_quantity_dimension(milli_mass_unit, mass)
|
||||
SI.set_quantity_scale_factor(milli_mass_unit, atomic_mass_unit/1000)
|
||||
|
||||
SI.set_quantity_dimension(quart, length ** 3)
|
||||
SI.set_quantity_scale_factor(quart, Rational(231, 4) * inch**3)
|
||||
|
||||
# Other convenient units and magnitudes
|
||||
|
||||
SI.set_quantity_dimension(lightyear, length)
|
||||
SI.set_quantity_scale_factor(lightyear, speed_of_light*julian_year)
|
||||
|
||||
SI.set_quantity_dimension(astronomical_unit, length)
|
||||
SI.set_quantity_scale_factor(astronomical_unit, 149597870691*meter)
|
||||
|
||||
# Fundamental Planck units:
|
||||
|
||||
SI.set_quantity_dimension(planck_mass, mass)
|
||||
SI.set_quantity_scale_factor(planck_mass, sqrt(hbar*speed_of_light/G))
|
||||
|
||||
SI.set_quantity_dimension(planck_time, time)
|
||||
SI.set_quantity_scale_factor(planck_time, sqrt(hbar*G/speed_of_light**5))
|
||||
|
||||
SI.set_quantity_dimension(planck_temperature, temperature)
|
||||
SI.set_quantity_scale_factor(planck_temperature, sqrt(hbar*speed_of_light**5/G/boltzmann**2))
|
||||
|
||||
SI.set_quantity_dimension(planck_length, length)
|
||||
SI.set_quantity_scale_factor(planck_length, sqrt(hbar*G/speed_of_light**3))
|
||||
|
||||
SI.set_quantity_dimension(planck_charge, charge)
|
||||
SI.set_quantity_scale_factor(planck_charge, sqrt(4*pi*electric_constant*hbar*speed_of_light))
|
||||
|
||||
# Derived Planck units:
|
||||
|
||||
SI.set_quantity_dimension(planck_area, length ** 2)
|
||||
SI.set_quantity_scale_factor(planck_area, planck_length**2)
|
||||
|
||||
SI.set_quantity_dimension(planck_volume, length ** 3)
|
||||
SI.set_quantity_scale_factor(planck_volume, planck_length**3)
|
||||
|
||||
SI.set_quantity_dimension(planck_momentum, mass * velocity)
|
||||
SI.set_quantity_scale_factor(planck_momentum, planck_mass * speed_of_light)
|
||||
|
||||
SI.set_quantity_dimension(planck_energy, energy)
|
||||
SI.set_quantity_scale_factor(planck_energy, planck_mass * speed_of_light**2)
|
||||
|
||||
SI.set_quantity_dimension(planck_force, force)
|
||||
SI.set_quantity_scale_factor(planck_force, planck_energy / planck_length)
|
||||
|
||||
SI.set_quantity_dimension(planck_power, power)
|
||||
SI.set_quantity_scale_factor(planck_power, planck_energy / planck_time)
|
||||
|
||||
SI.set_quantity_dimension(planck_density, mass / length ** 3)
|
||||
SI.set_quantity_scale_factor(planck_density, planck_mass / planck_length**3)
|
||||
|
||||
SI.set_quantity_dimension(planck_energy_density, energy / length ** 3)
|
||||
SI.set_quantity_scale_factor(planck_energy_density, planck_energy / planck_length**3)
|
||||
|
||||
SI.set_quantity_dimension(planck_intensity, mass * time ** (-3))
|
||||
SI.set_quantity_scale_factor(planck_intensity, planck_energy_density * speed_of_light)
|
||||
|
||||
SI.set_quantity_dimension(planck_angular_frequency, 1 / time)
|
||||
SI.set_quantity_scale_factor(planck_angular_frequency, 1 / planck_time)
|
||||
|
||||
SI.set_quantity_dimension(planck_pressure, pressure)
|
||||
SI.set_quantity_scale_factor(planck_pressure, planck_force / planck_length**2)
|
||||
|
||||
SI.set_quantity_dimension(planck_current, current)
|
||||
SI.set_quantity_scale_factor(planck_current, planck_charge / planck_time)
|
||||
|
||||
SI.set_quantity_dimension(planck_voltage, voltage)
|
||||
SI.set_quantity_scale_factor(planck_voltage, planck_energy / planck_charge)
|
||||
|
||||
SI.set_quantity_dimension(planck_impedance, impedance)
|
||||
SI.set_quantity_scale_factor(planck_impedance, planck_voltage / planck_current)
|
||||
|
||||
SI.set_quantity_dimension(planck_acceleration, acceleration)
|
||||
SI.set_quantity_scale_factor(planck_acceleration, speed_of_light / planck_time)
|
||||
|
||||
# Older units for radioactivity
|
||||
|
||||
SI.set_quantity_dimension(curie, 1 / time)
|
||||
SI.set_quantity_scale_factor(curie, 37000000000*becquerel)
|
||||
|
||||
SI.set_quantity_dimension(rutherford, 1 / time)
|
||||
SI.set_quantity_scale_factor(rutherford, 1000000*becquerel)
|
||||
|
||||
|
||||
# check that scale factors are the right SI dimensions:
|
||||
for _scale_factor, _dimension in zip(
|
||||
SI._quantity_scale_factors.values(),
|
||||
SI._quantity_dimension_map.values()
|
||||
):
|
||||
dimex = SI.get_dimensional_expr(_scale_factor)
|
||||
if dimex != 1:
|
||||
# XXX: equivalent_dims is an instance method taking two arguments in
|
||||
# addition to self so this can not work:
|
||||
if not DimensionSystem.equivalent_dims(_dimension, Dimension(dimex)): # type: ignore
|
||||
raise ValueError("quantity value and dimension mismatch")
|
||||
del _scale_factor, _dimension
|
||||
|
||||
__all__ = [
|
||||
'mmHg', 'atmosphere', 'inductance', 'newton', 'meter',
|
||||
'vacuum_permittivity', 'pascal', 'magnetic_constant', 'voltage',
|
||||
'angular_mil', 'luminous_intensity', 'all_units',
|
||||
'julian_year', 'weber', 'exbibyte', 'liter',
|
||||
'molar_gas_constant', 'faraday_constant', 'avogadro_constant',
|
||||
'lightyear', 'planck_density', 'gee', 'mol', 'bit', 'gray',
|
||||
'planck_momentum', 'bar', 'magnetic_density', 'prefix_unit', 'PREFIXES',
|
||||
'planck_time', 'dimex', 'gram', 'candela', 'force', 'planck_intensity',
|
||||
'energy', 'becquerel', 'planck_acceleration', 'speed_of_light',
|
||||
'conductance', 'frequency', 'coulomb_constant', 'degree', 'lux', 'planck',
|
||||
'current', 'planck_current', 'tebibyte', 'planck_power', 'MKSA', 'power',
|
||||
'K', 'planck_volume', 'quart', 'pressure', 'amount_of_substance',
|
||||
'joule', 'boltzmann_constant', 'Dimension', 'c', 'planck_force', 'length',
|
||||
'watt', 'action', 'hbar', 'gibibyte', 'DimensionSystem', 'cd', 'volt',
|
||||
'planck_charge', 'dioptre', 'vacuum_impedance', 'dimsys_default', 'farad',
|
||||
'charge', 'gravitational_constant', 'temperature', 'u0', 'hertz',
|
||||
'capacitance', 'tesla', 'steradian', 'planck_mass', 'josephson_constant',
|
||||
'planck_area', 'stefan_boltzmann_constant', 'base_dims',
|
||||
'astronomical_unit', 'radian', 'planck_voltage', 'impedance',
|
||||
'planck_energy', 'Da', 'atomic_mass_constant', 'rutherford', 'second', 'inch',
|
||||
'elementary_charge', 'SI', 'electronvolt', 'dimsys_SI', 'henry',
|
||||
'planck_angular_frequency', 'ohm', 'pound', 'planck_pressure', 'G', 'psi',
|
||||
'dHg0', 'von_klitzing_constant', 'planck_length', 'avogadro_number',
|
||||
'mole', 'acceleration', 'information', 'planck_energy_density',
|
||||
'mebibyte', 's', 'acceleration_due_to_gravity', 'electron_rest_mass',
|
||||
'planck_temperature', 'units', 'mass', 'dimsys_MKSA', 'kelvin', 'kPa',
|
||||
'boltzmann', 'milli_mass_unit', 'planck_impedance', 'electric_constant',
|
||||
'derived_dims', 'kg', 'coulomb', 'siemens', 'byte', 'magnetic_flux',
|
||||
'atomic_mass_unit', 'm', 'kibibyte', 'kilogram', 'One', 'curie', 'u',
|
||||
'time', 'pebibyte', 'velocity', 'ampere', 'katal',
|
||||
]
|
||||
@@ -0,0 +1,150 @@
|
||||
from sympy.physics.units.systems.si import dimsys_SI
|
||||
|
||||
from sympy.core.numbers import pi
|
||||
from sympy.core.singleton import S
|
||||
from sympy.core.symbol import Symbol
|
||||
from sympy.functions.elementary.complexes import Abs
|
||||
from sympy.functions.elementary.exponential import log
|
||||
from sympy.functions.elementary.miscellaneous import sqrt
|
||||
from sympy.functions.elementary.trigonometric import (acos, atan2, cos)
|
||||
from sympy.physics.units.dimensions import Dimension
|
||||
from sympy.physics.units.definitions.dimension_definitions import (
|
||||
length, time, mass, force, pressure, angle
|
||||
)
|
||||
from sympy.physics.units import foot
|
||||
from sympy.testing.pytest import raises
|
||||
|
||||
|
||||
def test_Dimension_definition():
|
||||
assert dimsys_SI.get_dimensional_dependencies(length) == {length: 1}
|
||||
assert length.name == Symbol("length")
|
||||
assert length.symbol == Symbol("L")
|
||||
|
||||
halflength = sqrt(length)
|
||||
assert dimsys_SI.get_dimensional_dependencies(halflength) == {length: S.Half}
|
||||
|
||||
|
||||
def test_Dimension_error_definition():
|
||||
# tuple with more or less than two entries
|
||||
raises(TypeError, lambda: Dimension(("length", 1, 2)))
|
||||
raises(TypeError, lambda: Dimension(["length"]))
|
||||
|
||||
# non-number power
|
||||
raises(TypeError, lambda: Dimension({"length": "a"}))
|
||||
|
||||
# non-number with named argument
|
||||
raises(TypeError, lambda: Dimension({"length": (1, 2)}))
|
||||
|
||||
# symbol should by Symbol or str
|
||||
raises(AssertionError, lambda: Dimension("length", symbol=1))
|
||||
|
||||
|
||||
def test_str():
|
||||
assert str(Dimension("length")) == "Dimension(length)"
|
||||
assert str(Dimension("length", "L")) == "Dimension(length, L)"
|
||||
|
||||
|
||||
def test_Dimension_properties():
|
||||
assert dimsys_SI.is_dimensionless(length) is False
|
||||
assert dimsys_SI.is_dimensionless(length/length) is True
|
||||
assert dimsys_SI.is_dimensionless(Dimension("undefined")) is False
|
||||
|
||||
assert length.has_integer_powers(dimsys_SI) is True
|
||||
assert (length**(-1)).has_integer_powers(dimsys_SI) is True
|
||||
assert (length**1.5).has_integer_powers(dimsys_SI) is False
|
||||
|
||||
|
||||
def test_Dimension_add_sub():
|
||||
assert length + length == length
|
||||
assert length - length == length
|
||||
assert -length == length
|
||||
|
||||
raises(TypeError, lambda: length + foot)
|
||||
raises(TypeError, lambda: foot + length)
|
||||
raises(TypeError, lambda: length - foot)
|
||||
raises(TypeError, lambda: foot - length)
|
||||
|
||||
# issue 14547 - only raise error for dimensional args; allow
|
||||
# others to pass
|
||||
x = Symbol('x')
|
||||
e = length + x
|
||||
assert e == x + length and e.is_Add and set(e.args) == {length, x}
|
||||
e = length + 1
|
||||
assert e == 1 + length == 1 - length and e.is_Add and set(e.args) == {length, 1}
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(mass * length / time**2 + force) == \
|
||||
{length: 1, mass: 1, time: -2}
|
||||
assert dimsys_SI.get_dimensional_dependencies(mass * length / time**2 + force -
|
||||
pressure * length**2) == \
|
||||
{length: 1, mass: 1, time: -2}
|
||||
|
||||
raises(TypeError, lambda: dimsys_SI.get_dimensional_dependencies(mass * length / time**2 + pressure))
|
||||
|
||||
def test_Dimension_mul_div_exp():
|
||||
assert 2*length == length*2 == length/2 == length
|
||||
assert 2/length == 1/length
|
||||
x = Symbol('x')
|
||||
m = x*length
|
||||
assert m == length*x and m.is_Mul and set(m.args) == {x, length}
|
||||
d = x/length
|
||||
assert d == x*length**-1 and d.is_Mul and set(d.args) == {x, 1/length}
|
||||
d = length/x
|
||||
assert d == length*x**-1 and d.is_Mul and set(d.args) == {1/x, length}
|
||||
|
||||
velo = length / time
|
||||
|
||||
assert (length * length) == length ** 2
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(length * length) == {length: 2}
|
||||
assert dimsys_SI.get_dimensional_dependencies(length ** 2) == {length: 2}
|
||||
assert dimsys_SI.get_dimensional_dependencies(length * time) == {length: 1, time: 1}
|
||||
assert dimsys_SI.get_dimensional_dependencies(velo) == {length: 1, time: -1}
|
||||
assert dimsys_SI.get_dimensional_dependencies(velo ** 2) == {length: 2, time: -2}
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(length / length) == {}
|
||||
assert dimsys_SI.get_dimensional_dependencies(velo / length * time) == {}
|
||||
assert dimsys_SI.get_dimensional_dependencies(length ** -1) == {length: -1}
|
||||
assert dimsys_SI.get_dimensional_dependencies(velo ** -1.5) == {length: -1.5, time: 1.5}
|
||||
|
||||
length_a = length**"a"
|
||||
assert dimsys_SI.get_dimensional_dependencies(length_a) == {length: Symbol("a")}
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(length**pi) == {length: pi}
|
||||
assert dimsys_SI.get_dimensional_dependencies(length**(length/length)) == {length: Dimension(1)}
|
||||
|
||||
raises(TypeError, lambda: dimsys_SI.get_dimensional_dependencies(length**length))
|
||||
|
||||
assert length != 1
|
||||
assert length / length != 1
|
||||
|
||||
length_0 = length ** 0
|
||||
assert dimsys_SI.get_dimensional_dependencies(length_0) == {}
|
||||
|
||||
# issue 18738
|
||||
a = Symbol('a')
|
||||
b = Symbol('b')
|
||||
c = sqrt(a**2 + b**2)
|
||||
c_dim = c.subs({a: length, b: length})
|
||||
assert dimsys_SI.equivalent_dims(c_dim, length)
|
||||
|
||||
def test_Dimension_functions():
|
||||
raises(TypeError, lambda: dimsys_SI.get_dimensional_dependencies(cos(length)))
|
||||
raises(TypeError, lambda: dimsys_SI.get_dimensional_dependencies(acos(angle)))
|
||||
raises(TypeError, lambda: dimsys_SI.get_dimensional_dependencies(atan2(length, time)))
|
||||
raises(TypeError, lambda: dimsys_SI.get_dimensional_dependencies(log(length)))
|
||||
raises(TypeError, lambda: dimsys_SI.get_dimensional_dependencies(log(100, length)))
|
||||
raises(TypeError, lambda: dimsys_SI.get_dimensional_dependencies(log(length, 10)))
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(pi) == {}
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(cos(1)) == {}
|
||||
assert dimsys_SI.get_dimensional_dependencies(cos(angle)) == {}
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(atan2(length, length)) == {}
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(log(length / length, length / length)) == {}
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(Abs(length)) == {length: 1}
|
||||
assert dimsys_SI.get_dimensional_dependencies(Abs(length / length)) == {}
|
||||
|
||||
assert dimsys_SI.get_dimensional_dependencies(sqrt(-1)) == {}
|
||||
@@ -0,0 +1,95 @@
|
||||
from sympy.core.symbol import symbols
|
||||
from sympy.matrices.dense import (Matrix, eye)
|
||||
from sympy.physics.units.definitions.dimension_definitions import (
|
||||
action, current, length, mass, time,
|
||||
velocity)
|
||||
from sympy.physics.units.dimensions import DimensionSystem
|
||||
|
||||
|
||||
def test_extend():
|
||||
ms = DimensionSystem((length, time), (velocity,))
|
||||
|
||||
mks = ms.extend((mass,), (action,))
|
||||
|
||||
res = DimensionSystem((length, time, mass), (velocity, action))
|
||||
assert mks.base_dims == res.base_dims
|
||||
assert mks.derived_dims == res.derived_dims
|
||||
|
||||
|
||||
def test_list_dims():
|
||||
dimsys = DimensionSystem((length, time, mass))
|
||||
|
||||
assert dimsys.list_can_dims == (length, mass, time)
|
||||
|
||||
|
||||
def test_dim_can_vector():
|
||||
dimsys = DimensionSystem(
|
||||
[length, mass, time],
|
||||
[velocity, action],
|
||||
{
|
||||
velocity: {length: 1, time: -1}
|
||||
}
|
||||
)
|
||||
|
||||
assert dimsys.dim_can_vector(length) == Matrix([1, 0, 0])
|
||||
assert dimsys.dim_can_vector(velocity) == Matrix([1, 0, -1])
|
||||
|
||||
dimsys = DimensionSystem(
|
||||
(length, velocity, action),
|
||||
(mass, time),
|
||||
{
|
||||
time: {length: 1, velocity: -1}
|
||||
}
|
||||
)
|
||||
|
||||
assert dimsys.dim_can_vector(length) == Matrix([0, 1, 0])
|
||||
assert dimsys.dim_can_vector(velocity) == Matrix([0, 0, 1])
|
||||
assert dimsys.dim_can_vector(time) == Matrix([0, 1, -1])
|
||||
|
||||
dimsys = DimensionSystem(
|
||||
(length, mass, time),
|
||||
(velocity, action),
|
||||
{velocity: {length: 1, time: -1},
|
||||
action: {mass: 1, length: 2, time: -1}})
|
||||
|
||||
assert dimsys.dim_vector(length) == Matrix([1, 0, 0])
|
||||
assert dimsys.dim_vector(velocity) == Matrix([1, 0, -1])
|
||||
|
||||
|
||||
def test_inv_can_transf_matrix():
|
||||
dimsys = DimensionSystem((length, mass, time))
|
||||
assert dimsys.inv_can_transf_matrix == eye(3)
|
||||
|
||||
|
||||
def test_can_transf_matrix():
|
||||
dimsys = DimensionSystem((length, mass, time))
|
||||
assert dimsys.can_transf_matrix == eye(3)
|
||||
|
||||
dimsys = DimensionSystem((length, velocity, action))
|
||||
assert dimsys.can_transf_matrix == eye(3)
|
||||
|
||||
dimsys = DimensionSystem((length, time), (velocity,), {velocity: {length: 1, time: -1}})
|
||||
assert dimsys.can_transf_matrix == eye(2)
|
||||
|
||||
|
||||
def test_is_consistent():
|
||||
assert DimensionSystem((length, time)).is_consistent is True
|
||||
|
||||
|
||||
def test_print_dim_base():
|
||||
mksa = DimensionSystem(
|
||||
(length, time, mass, current),
|
||||
(action,),
|
||||
{action: {mass: 1, length: 2, time: -1}})
|
||||
L, M, T = symbols("L M T")
|
||||
assert mksa.print_dim_base(action) == L**2*M/T
|
||||
|
||||
|
||||
def test_dim():
|
||||
dimsys = DimensionSystem(
|
||||
(length, mass, time),
|
||||
(velocity, action),
|
||||
{velocity: {length: 1, time: -1},
|
||||
action: {mass: 1, length: 2, time: -1}}
|
||||
)
|
||||
assert dimsys.dim == 3
|
||||
@@ -0,0 +1,86 @@
|
||||
from sympy.core.mul import Mul
|
||||
from sympy.core.numbers import Rational
|
||||
from sympy.core.singleton import S
|
||||
from sympy.core.symbol import (Symbol, symbols)
|
||||
from sympy.physics.units import Quantity, length, meter, W
|
||||
from sympy.physics.units.prefixes import PREFIXES, Prefix, prefix_unit, kilo, \
|
||||
kibi
|
||||
from sympy.physics.units.systems import SI
|
||||
|
||||
x = Symbol('x')
|
||||
|
||||
|
||||
def test_prefix_operations():
|
||||
m = PREFIXES['m']
|
||||
k = PREFIXES['k']
|
||||
M = PREFIXES['M']
|
||||
|
||||
dodeca = Prefix('dodeca', 'dd', 1, base=12)
|
||||
|
||||
assert m * k is S.One
|
||||
assert m * W == W / 1000
|
||||
assert k * k == M
|
||||
assert 1 / m == k
|
||||
assert k / m == M
|
||||
|
||||
assert dodeca * dodeca == 144
|
||||
assert 1 / dodeca == S.One / 12
|
||||
assert k / dodeca == S(1000) / 12
|
||||
assert dodeca / dodeca is S.One
|
||||
|
||||
m = Quantity("fake_meter")
|
||||
SI.set_quantity_dimension(m, S.One)
|
||||
SI.set_quantity_scale_factor(m, S.One)
|
||||
|
||||
assert dodeca * m == 12 * m
|
||||
assert dodeca / m == 12 / m
|
||||
|
||||
expr1 = kilo * 3
|
||||
assert isinstance(expr1, Mul)
|
||||
assert expr1.args == (3, kilo)
|
||||
|
||||
expr2 = kilo * x
|
||||
assert isinstance(expr2, Mul)
|
||||
assert expr2.args == (x, kilo)
|
||||
|
||||
expr3 = kilo / 3
|
||||
assert isinstance(expr3, Mul)
|
||||
assert expr3.args == (Rational(1, 3), kilo)
|
||||
assert expr3.args == (S.One/3, kilo)
|
||||
|
||||
expr4 = kilo / x
|
||||
assert isinstance(expr4, Mul)
|
||||
assert expr4.args == (1/x, kilo)
|
||||
|
||||
|
||||
def test_prefix_unit():
|
||||
m = Quantity("fake_meter", abbrev="m")
|
||||
m.set_global_relative_scale_factor(1, meter)
|
||||
|
||||
pref = {"m": PREFIXES["m"], "c": PREFIXES["c"], "d": PREFIXES["d"]}
|
||||
|
||||
q1 = Quantity("millifake_meter", abbrev="mm")
|
||||
q2 = Quantity("centifake_meter", abbrev="cm")
|
||||
q3 = Quantity("decifake_meter", abbrev="dm")
|
||||
|
||||
SI.set_quantity_dimension(q1, length)
|
||||
|
||||
SI.set_quantity_scale_factor(q1, PREFIXES["m"])
|
||||
SI.set_quantity_scale_factor(q1, PREFIXES["c"])
|
||||
SI.set_quantity_scale_factor(q1, PREFIXES["d"])
|
||||
|
||||
res = [q1, q2, q3]
|
||||
|
||||
prefs = prefix_unit(m, pref)
|
||||
assert set(prefs) == set(res)
|
||||
assert {v.abbrev for v in prefs} == set(symbols("mm,cm,dm"))
|
||||
|
||||
|
||||
def test_bases():
|
||||
assert kilo.base == 10
|
||||
assert kibi.base == 2
|
||||
|
||||
|
||||
def test_repr():
|
||||
assert eval(repr(kilo)) == kilo
|
||||
assert eval(repr(kibi)) == kibi
|
||||
@@ -0,0 +1,575 @@
|
||||
import warnings
|
||||
|
||||
from sympy.core.add import Add
|
||||
from sympy.core.function import (Function, diff)
|
||||
from sympy.core.numbers import (Number, Rational)
|
||||
from sympy.core.singleton import S
|
||||
from sympy.core.symbol import (Symbol, symbols)
|
||||
from sympy.functions.elementary.complexes import Abs
|
||||
from sympy.functions.elementary.exponential import (exp, log)
|
||||
from sympy.functions.elementary.miscellaneous import sqrt
|
||||
from sympy.functions.elementary.trigonometric import sin
|
||||
from sympy.integrals.integrals import integrate
|
||||
from sympy.physics.units import (amount_of_substance, area, convert_to, find_unit,
|
||||
volume, kilometer, joule, molar_gas_constant,
|
||||
vacuum_permittivity, elementary_charge, volt,
|
||||
ohm)
|
||||
from sympy.physics.units.definitions import (amu, au, centimeter, coulomb,
|
||||
day, foot, grams, hour, inch, kg, km, m, meter, millimeter,
|
||||
minute, quart, s, second, speed_of_light, bit,
|
||||
byte, kibibyte, mebibyte, gibibyte, tebibyte, pebibyte, exbibyte,
|
||||
kilogram, gravitational_constant, electron_rest_mass)
|
||||
|
||||
from sympy.physics.units.definitions.dimension_definitions import (
|
||||
Dimension, charge, length, time, temperature, pressure,
|
||||
energy, mass
|
||||
)
|
||||
from sympy.physics.units.prefixes import PREFIXES, kilo
|
||||
from sympy.physics.units.quantities import PhysicalConstant, Quantity
|
||||
from sympy.physics.units.systems import SI
|
||||
from sympy.testing.pytest import raises
|
||||
|
||||
k = PREFIXES["k"]
|
||||
|
||||
|
||||
def test_str_repr():
|
||||
assert str(kg) == "kilogram"
|
||||
|
||||
|
||||
def test_eq():
|
||||
# simple test
|
||||
assert 10*m == 10*m
|
||||
assert 10*m != 10*s
|
||||
|
||||
|
||||
def test_convert_to():
|
||||
q = Quantity("q1")
|
||||
q.set_global_relative_scale_factor(S(5000), meter)
|
||||
|
||||
assert q.convert_to(m) == 5000*m
|
||||
|
||||
assert speed_of_light.convert_to(m / s) == 299792458 * m / s
|
||||
assert day.convert_to(s) == 86400*s
|
||||
|
||||
# Wrong dimension to convert:
|
||||
assert q.convert_to(s) == q
|
||||
assert speed_of_light.convert_to(m) == speed_of_light
|
||||
|
||||
expr = joule*second
|
||||
conv = convert_to(expr, joule)
|
||||
assert conv == joule*second
|
||||
|
||||
|
||||
def test_Quantity_definition():
|
||||
q = Quantity("s10", abbrev="sabbr")
|
||||
q.set_global_relative_scale_factor(10, second)
|
||||
u = Quantity("u", abbrev="dam")
|
||||
u.set_global_relative_scale_factor(10, meter)
|
||||
km = Quantity("km")
|
||||
km.set_global_relative_scale_factor(kilo, meter)
|
||||
v = Quantity("u")
|
||||
v.set_global_relative_scale_factor(5*kilo, meter)
|
||||
|
||||
assert q.scale_factor == 10
|
||||
assert q.dimension == time
|
||||
assert q.abbrev == Symbol("sabbr")
|
||||
|
||||
assert u.dimension == length
|
||||
assert u.scale_factor == 10
|
||||
assert u.abbrev == Symbol("dam")
|
||||
|
||||
assert km.scale_factor == 1000
|
||||
assert km.func(*km.args) == km
|
||||
assert km.func(*km.args).args == km.args
|
||||
|
||||
assert v.dimension == length
|
||||
assert v.scale_factor == 5000
|
||||
|
||||
|
||||
def test_abbrev():
|
||||
u = Quantity("u")
|
||||
u.set_global_relative_scale_factor(S.One, meter)
|
||||
|
||||
assert u.name == Symbol("u")
|
||||
assert u.abbrev == Symbol("u")
|
||||
|
||||
u = Quantity("u", abbrev="om")
|
||||
u.set_global_relative_scale_factor(S(2), meter)
|
||||
|
||||
assert u.name == Symbol("u")
|
||||
assert u.abbrev == Symbol("om")
|
||||
assert u.scale_factor == 2
|
||||
assert isinstance(u.scale_factor, Number)
|
||||
|
||||
u = Quantity("u", abbrev="ikm")
|
||||
u.set_global_relative_scale_factor(3*kilo, meter)
|
||||
|
||||
assert u.abbrev == Symbol("ikm")
|
||||
assert u.scale_factor == 3000
|
||||
|
||||
|
||||
def test_print():
|
||||
u = Quantity("unitname", abbrev="dam")
|
||||
assert repr(u) == "unitname"
|
||||
assert str(u) == "unitname"
|
||||
|
||||
|
||||
def test_Quantity_eq():
|
||||
u = Quantity("u", abbrev="dam")
|
||||
v = Quantity("v1")
|
||||
assert u != v
|
||||
v = Quantity("v2", abbrev="ds")
|
||||
assert u != v
|
||||
v = Quantity("v3", abbrev="dm")
|
||||
assert u != v
|
||||
|
||||
|
||||
def test_add_sub():
|
||||
u = Quantity("u")
|
||||
v = Quantity("v")
|
||||
w = Quantity("w")
|
||||
|
||||
u.set_global_relative_scale_factor(S(10), meter)
|
||||
v.set_global_relative_scale_factor(S(5), meter)
|
||||
w.set_global_relative_scale_factor(S(2), second)
|
||||
|
||||
assert isinstance(u + v, Add)
|
||||
assert (u + v.convert_to(u)) == (1 + S.Half)*u
|
||||
assert isinstance(u - v, Add)
|
||||
assert (u - v.convert_to(u)) == S.Half*u
|
||||
|
||||
|
||||
def test_quantity_abs():
|
||||
v_w1 = Quantity('v_w1')
|
||||
v_w2 = Quantity('v_w2')
|
||||
v_w3 = Quantity('v_w3')
|
||||
|
||||
v_w1.set_global_relative_scale_factor(1, meter/second)
|
||||
v_w2.set_global_relative_scale_factor(1, meter/second)
|
||||
v_w3.set_global_relative_scale_factor(1, meter/second)
|
||||
|
||||
expr = v_w3 - Abs(v_w1 - v_w2)
|
||||
|
||||
assert SI.get_dimensional_expr(v_w1) == (length/time).name
|
||||
|
||||
Dq = Dimension(SI.get_dimensional_expr(expr))
|
||||
|
||||
assert SI.get_dimension_system().get_dimensional_dependencies(Dq) == {
|
||||
length: 1,
|
||||
time: -1,
|
||||
}
|
||||
assert meter == sqrt(meter**2)
|
||||
|
||||
|
||||
def test_check_unit_consistency():
|
||||
u = Quantity("u")
|
||||
v = Quantity("v")
|
||||
w = Quantity("w")
|
||||
|
||||
u.set_global_relative_scale_factor(S(10), meter)
|
||||
v.set_global_relative_scale_factor(S(5), meter)
|
||||
w.set_global_relative_scale_factor(S(2), second)
|
||||
|
||||
def check_unit_consistency(expr):
|
||||
SI._collect_factor_and_dimension(expr)
|
||||
|
||||
raises(ValueError, lambda: check_unit_consistency(u + w))
|
||||
raises(ValueError, lambda: check_unit_consistency(u - w))
|
||||
raises(ValueError, lambda: check_unit_consistency(u + 1))
|
||||
raises(ValueError, lambda: check_unit_consistency(u - 1))
|
||||
raises(ValueError, lambda: check_unit_consistency(1 - exp(u / w)))
|
||||
|
||||
|
||||
def test_mul_div():
|
||||
u = Quantity("u")
|
||||
v = Quantity("v")
|
||||
t = Quantity("t")
|
||||
ut = Quantity("ut")
|
||||
v2 = Quantity("v")
|
||||
|
||||
u.set_global_relative_scale_factor(S(10), meter)
|
||||
v.set_global_relative_scale_factor(S(5), meter)
|
||||
t.set_global_relative_scale_factor(S(2), second)
|
||||
ut.set_global_relative_scale_factor(S(20), meter*second)
|
||||
v2.set_global_relative_scale_factor(S(5), meter/second)
|
||||
|
||||
assert 1 / u == u**(-1)
|
||||
assert u / 1 == u
|
||||
|
||||
v1 = u / t
|
||||
v2 = v
|
||||
|
||||
# Pow only supports structural equality:
|
||||
assert v1 != v2
|
||||
assert v1 == v2.convert_to(v1)
|
||||
|
||||
# TODO: decide whether to allow such expression in the future
|
||||
# (requires somehow manipulating the core).
|
||||
# assert u / Quantity('l2', dimension=length, scale_factor=2) == 5
|
||||
|
||||
assert u * 1 == u
|
||||
|
||||
ut1 = u * t
|
||||
ut2 = ut
|
||||
|
||||
# Mul only supports structural equality:
|
||||
assert ut1 != ut2
|
||||
assert ut1 == ut2.convert_to(ut1)
|
||||
|
||||
# Mul only supports structural equality:
|
||||
lp1 = Quantity("lp1")
|
||||
lp1.set_global_relative_scale_factor(S(2), 1/meter)
|
||||
assert u * lp1 != 20
|
||||
|
||||
assert u**0 == 1
|
||||
assert u**1 == u
|
||||
|
||||
# TODO: Pow only support structural equality:
|
||||
u2 = Quantity("u2")
|
||||
u3 = Quantity("u3")
|
||||
u2.set_global_relative_scale_factor(S(100), meter**2)
|
||||
u3.set_global_relative_scale_factor(Rational(1, 10), 1/meter)
|
||||
|
||||
assert u ** 2 != u2
|
||||
assert u ** -1 != u3
|
||||
|
||||
assert u ** 2 == u2.convert_to(u)
|
||||
assert u ** -1 == u3.convert_to(u)
|
||||
|
||||
|
||||
def test_units():
|
||||
assert convert_to((5*m/s * day) / km, 1) == 432
|
||||
assert convert_to(foot / meter, meter) == Rational(3048, 10000)
|
||||
# amu is a pure mass so mass/mass gives a number, not an amount (mol)
|
||||
# TODO: need better simplification routine:
|
||||
assert str(convert_to(grams/amu, grams).n(2)) == '6.0e+23'
|
||||
|
||||
# Light from the sun needs about 8.3 minutes to reach earth
|
||||
t = (1*au / speed_of_light) / minute
|
||||
# TODO: need a better way to simplify expressions containing units:
|
||||
t = convert_to(convert_to(t, meter / minute), meter)
|
||||
assert t.simplify() == Rational(49865956897, 5995849160)
|
||||
|
||||
# TODO: fix this, it should give `m` without `Abs`
|
||||
assert sqrt(m**2) == m
|
||||
assert (sqrt(m))**2 == m
|
||||
|
||||
t = Symbol('t')
|
||||
assert integrate(t*m/s, (t, 1*s, 5*s)) == 12*m*s
|
||||
assert (t * m/s).integrate((t, 1*s, 5*s)) == 12*m*s
|
||||
|
||||
|
||||
def test_issue_quart():
|
||||
assert convert_to(4 * quart / inch ** 3, meter) == 231
|
||||
assert convert_to(4 * quart / inch ** 3, millimeter) == 231
|
||||
|
||||
def test_electron_rest_mass():
|
||||
assert convert_to(electron_rest_mass, kilogram) == 9.1093837015e-31*kilogram
|
||||
assert convert_to(electron_rest_mass, grams) == 9.1093837015e-28*grams
|
||||
|
||||
def test_issue_5565():
|
||||
assert (m < s).is_Relational
|
||||
|
||||
|
||||
def test_find_unit():
|
||||
assert find_unit('coulomb') == ['coulomb', 'coulombs', 'coulomb_constant']
|
||||
assert find_unit(coulomb) == ['C', 'coulomb', 'coulombs', 'planck_charge', 'elementary_charge']
|
||||
assert find_unit(charge) == ['C', 'coulomb', 'coulombs', 'planck_charge', 'elementary_charge']
|
||||
assert find_unit(inch) == [
|
||||
'm', 'au', 'cm', 'dm', 'ft', 'km', 'ly', 'mi', 'mm', 'nm', 'pm', 'um', 'yd',
|
||||
'nmi', 'feet', 'foot', 'inch', 'mile', 'yard', 'meter', 'miles', 'yards',
|
||||
'inches', 'meters', 'micron', 'microns', 'angstrom', 'angstroms', 'decimeter',
|
||||
'kilometer', 'lightyear', 'nanometer', 'picometer', 'centimeter', 'decimeters',
|
||||
'kilometers', 'lightyears', 'micrometer', 'millimeter', 'nanometers', 'picometers',
|
||||
'centimeters', 'micrometers', 'millimeters', 'nautical_mile', 'planck_length',
|
||||
'nautical_miles', 'astronomical_unit', 'astronomical_units']
|
||||
assert find_unit(inch**-1) == ['D', 'dioptre', 'optical_power']
|
||||
assert find_unit(length**-1) == ['D', 'dioptre', 'optical_power']
|
||||
assert find_unit(inch ** 2) == ['ha', 'hectare', 'planck_area']
|
||||
assert find_unit(inch ** 3) == [
|
||||
'L', 'l', 'cL', 'cl', 'dL', 'dl', 'mL', 'ml', 'liter', 'quart', 'liters', 'quarts',
|
||||
'deciliter', 'centiliter', 'deciliters', 'milliliter',
|
||||
'centiliters', 'milliliters', 'planck_volume']
|
||||
assert find_unit('voltage') == ['V', 'v', 'volt', 'volts', 'planck_voltage']
|
||||
assert find_unit(grams) == ['g', 't', 'Da', 'kg', 'me', 'mg', 'ug', 'amu', 'mmu', 'amus',
|
||||
'gram', 'mmus', 'grams', 'pound', 'tonne', 'dalton', 'pounds',
|
||||
'kilogram', 'kilograms', 'microgram', 'milligram', 'metric_ton',
|
||||
'micrograms', 'milligrams', 'planck_mass', 'milli_mass_unit', 'atomic_mass_unit',
|
||||
'electron_rest_mass', 'atomic_mass_constant']
|
||||
|
||||
|
||||
def test_Quantity_derivative():
|
||||
x = symbols("x")
|
||||
assert diff(x*meter, x) == meter
|
||||
assert diff(x**3*meter**2, x) == 3*x**2*meter**2
|
||||
assert diff(meter, meter) == 1
|
||||
assert diff(meter**2, meter) == 2*meter
|
||||
|
||||
|
||||
def test_quantity_postprocessing():
|
||||
q1 = Quantity('q1')
|
||||
q2 = Quantity('q2')
|
||||
|
||||
SI.set_quantity_dimension(q1, length*pressure**2*temperature/time)
|
||||
SI.set_quantity_dimension(q2, energy*pressure*temperature/(length**2*time))
|
||||
|
||||
assert q1 + q2
|
||||
q = q1 + q2
|
||||
Dq = Dimension(SI.get_dimensional_expr(q))
|
||||
assert SI.get_dimension_system().get_dimensional_dependencies(Dq) == {
|
||||
length: -1,
|
||||
mass: 2,
|
||||
temperature: 1,
|
||||
time: -5,
|
||||
}
|
||||
|
||||
|
||||
def test_factor_and_dimension():
|
||||
assert (3000, Dimension(1)) == SI._collect_factor_and_dimension(3000)
|
||||
assert (1001, length) == SI._collect_factor_and_dimension(meter + km)
|
||||
assert (2, length/time) == SI._collect_factor_and_dimension(
|
||||
meter/second + 36*km/(10*hour))
|
||||
|
||||
x, y = symbols('x y')
|
||||
assert (x + y/100, length) == SI._collect_factor_and_dimension(
|
||||
x*m + y*centimeter)
|
||||
|
||||
cH = Quantity('cH')
|
||||
SI.set_quantity_dimension(cH, amount_of_substance/volume)
|
||||
|
||||
pH = -log(cH)
|
||||
|
||||
assert (1, volume/amount_of_substance) == SI._collect_factor_and_dimension(
|
||||
exp(pH))
|
||||
|
||||
v_w1 = Quantity('v_w1')
|
||||
v_w2 = Quantity('v_w2')
|
||||
|
||||
v_w1.set_global_relative_scale_factor(Rational(3, 2), meter/second)
|
||||
v_w2.set_global_relative_scale_factor(2, meter/second)
|
||||
|
||||
expr = Abs(v_w1/2 - v_w2)
|
||||
assert (Rational(5, 4), length/time) == \
|
||||
SI._collect_factor_and_dimension(expr)
|
||||
|
||||
expr = Rational(5, 2)*second/meter*v_w1 - 3000
|
||||
assert (-(2996 + Rational(1, 4)), Dimension(1)) == \
|
||||
SI._collect_factor_and_dimension(expr)
|
||||
|
||||
expr = v_w1**(v_w2/v_w1)
|
||||
assert ((Rational(3, 2))**Rational(4, 3), (length/time)**Rational(4, 3)) == \
|
||||
SI._collect_factor_and_dimension(expr)
|
||||
|
||||
|
||||
def test_dimensional_expr_of_derivative():
|
||||
l = Quantity('l')
|
||||
t = Quantity('t')
|
||||
t1 = Quantity('t1')
|
||||
l.set_global_relative_scale_factor(36, km)
|
||||
t.set_global_relative_scale_factor(1, hour)
|
||||
t1.set_global_relative_scale_factor(1, second)
|
||||
x = Symbol('x')
|
||||
y = Symbol('y')
|
||||
f = Function('f')
|
||||
dfdx = f(x, y).diff(x, y)
|
||||
dl_dt = dfdx.subs({f(x, y): l, x: t, y: t1})
|
||||
assert SI.get_dimensional_expr(dl_dt) ==\
|
||||
SI.get_dimensional_expr(l / t / t1) ==\
|
||||
Symbol("length")/Symbol("time")**2
|
||||
assert SI._collect_factor_and_dimension(dl_dt) ==\
|
||||
SI._collect_factor_and_dimension(l / t / t1) ==\
|
||||
(10, length/time**2)
|
||||
|
||||
|
||||
def test_get_dimensional_expr_with_function():
|
||||
v_w1 = Quantity('v_w1')
|
||||
v_w2 = Quantity('v_w2')
|
||||
v_w1.set_global_relative_scale_factor(1, meter/second)
|
||||
v_w2.set_global_relative_scale_factor(1, meter/second)
|
||||
|
||||
assert SI.get_dimensional_expr(sin(v_w1)) == \
|
||||
sin(SI.get_dimensional_expr(v_w1))
|
||||
assert SI.get_dimensional_expr(sin(v_w1/v_w2)) == 1
|
||||
|
||||
|
||||
def test_binary_information():
|
||||
assert convert_to(kibibyte, byte) == 1024*byte
|
||||
assert convert_to(mebibyte, byte) == 1024**2*byte
|
||||
assert convert_to(gibibyte, byte) == 1024**3*byte
|
||||
assert convert_to(tebibyte, byte) == 1024**4*byte
|
||||
assert convert_to(pebibyte, byte) == 1024**5*byte
|
||||
assert convert_to(exbibyte, byte) == 1024**6*byte
|
||||
|
||||
assert kibibyte.convert_to(bit) == 8*1024*bit
|
||||
assert byte.convert_to(bit) == 8*bit
|
||||
|
||||
a = 10*kibibyte*hour
|
||||
|
||||
assert convert_to(a, byte) == 10240*byte*hour
|
||||
assert convert_to(a, minute) == 600*kibibyte*minute
|
||||
assert convert_to(a, [byte, minute]) == 614400*byte*minute
|
||||
|
||||
|
||||
def test_conversion_with_2_nonstandard_dimensions():
|
||||
good_grade = Quantity("good_grade")
|
||||
kilo_good_grade = Quantity("kilo_good_grade")
|
||||
centi_good_grade = Quantity("centi_good_grade")
|
||||
|
||||
kilo_good_grade.set_global_relative_scale_factor(1000, good_grade)
|
||||
centi_good_grade.set_global_relative_scale_factor(S.One/10**5, kilo_good_grade)
|
||||
|
||||
charity_points = Quantity("charity_points")
|
||||
milli_charity_points = Quantity("milli_charity_points")
|
||||
missions = Quantity("missions")
|
||||
|
||||
milli_charity_points.set_global_relative_scale_factor(S.One/1000, charity_points)
|
||||
missions.set_global_relative_scale_factor(251, charity_points)
|
||||
|
||||
assert convert_to(
|
||||
kilo_good_grade*milli_charity_points*millimeter,
|
||||
[centi_good_grade, missions, centimeter]
|
||||
) == S.One * 10**5 / (251*1000) / 10 * centi_good_grade*missions*centimeter
|
||||
|
||||
|
||||
def test_eval_subs():
|
||||
energy, mass, force = symbols('energy mass force')
|
||||
expr1 = energy/mass
|
||||
units = {energy: kilogram*meter**2/second**2, mass: kilogram}
|
||||
assert expr1.subs(units) == meter**2/second**2
|
||||
expr2 = force/mass
|
||||
units = {force:gravitational_constant*kilogram**2/meter**2, mass:kilogram}
|
||||
assert expr2.subs(units) == gravitational_constant*kilogram/meter**2
|
||||
|
||||
|
||||
def test_issue_14932():
|
||||
assert (log(inch) - log(2)).simplify() == log(inch/2)
|
||||
assert (log(inch) - log(foot)).simplify() == -log(12)
|
||||
p = symbols('p', positive=True)
|
||||
assert (log(inch) - log(p)).simplify() == log(inch/p)
|
||||
|
||||
|
||||
def test_issue_14547():
|
||||
# the root issue is that an argument with dimensions should
|
||||
# not raise an error when the `arg - 1` calculation is
|
||||
# performed in the assumptions system
|
||||
from sympy.physics.units import foot, inch
|
||||
from sympy.core.relational import Eq
|
||||
assert log(foot).is_zero is None
|
||||
assert log(foot).is_positive is None
|
||||
assert log(foot).is_nonnegative is None
|
||||
assert log(foot).is_negative is None
|
||||
assert log(foot).is_algebraic is None
|
||||
assert log(foot).is_rational is None
|
||||
# doesn't raise error
|
||||
assert Eq(log(foot), log(inch)) is not None # might be False or unevaluated
|
||||
|
||||
x = Symbol('x')
|
||||
e = foot + x
|
||||
assert e.is_Add and set(e.args) == {foot, x}
|
||||
e = foot + 1
|
||||
assert e.is_Add and set(e.args) == {foot, 1}
|
||||
|
||||
|
||||
def test_issue_22164():
|
||||
warnings.simplefilter("error")
|
||||
dm = Quantity("dm")
|
||||
SI.set_quantity_dimension(dm, length)
|
||||
SI.set_quantity_scale_factor(dm, 1)
|
||||
|
||||
bad_exp = Quantity("bad_exp")
|
||||
SI.set_quantity_dimension(bad_exp, length)
|
||||
SI.set_quantity_scale_factor(bad_exp, 1)
|
||||
|
||||
expr = dm ** bad_exp
|
||||
|
||||
# deprecation warning is not expected here
|
||||
SI._collect_factor_and_dimension(expr)
|
||||
|
||||
|
||||
def test_issue_22819():
|
||||
from sympy.physics.units import tonne, gram, Da
|
||||
from sympy.physics.units.systems.si import dimsys_SI
|
||||
assert tonne.convert_to(gram) == 1000000*gram
|
||||
assert dimsys_SI.get_dimensional_dependencies(area) == {length: 2}
|
||||
assert Da.scale_factor == 1.66053906660000e-24
|
||||
|
||||
|
||||
def test_issue_20288():
|
||||
from sympy.core.numbers import E
|
||||
from sympy.physics.units import energy
|
||||
u = Quantity('u')
|
||||
v = Quantity('v')
|
||||
SI.set_quantity_dimension(u, energy)
|
||||
SI.set_quantity_dimension(v, energy)
|
||||
u.set_global_relative_scale_factor(1, joule)
|
||||
v.set_global_relative_scale_factor(1, joule)
|
||||
expr = 1 + exp(u**2/v**2)
|
||||
assert SI._collect_factor_and_dimension(expr) == (1 + E, Dimension(1))
|
||||
|
||||
|
||||
def test_issue_24062():
|
||||
from sympy.core.numbers import E
|
||||
from sympy.physics.units import impedance, capacitance, time, ohm, farad, second
|
||||
|
||||
R = Quantity('R')
|
||||
C = Quantity('C')
|
||||
T = Quantity('T')
|
||||
SI.set_quantity_dimension(R, impedance)
|
||||
SI.set_quantity_dimension(C, capacitance)
|
||||
SI.set_quantity_dimension(T, time)
|
||||
R.set_global_relative_scale_factor(1, ohm)
|
||||
C.set_global_relative_scale_factor(1, farad)
|
||||
T.set_global_relative_scale_factor(1, second)
|
||||
expr = T / (R * C)
|
||||
dim = SI._collect_factor_and_dimension(expr)[1]
|
||||
assert SI.get_dimension_system().is_dimensionless(dim)
|
||||
|
||||
exp_expr = 1 + exp(expr)
|
||||
assert SI._collect_factor_and_dimension(exp_expr) == (1 + E, Dimension(1))
|
||||
|
||||
def test_issue_24211():
|
||||
from sympy.physics.units import time, velocity, acceleration, second, meter
|
||||
V1 = Quantity('V1')
|
||||
SI.set_quantity_dimension(V1, velocity)
|
||||
SI.set_quantity_scale_factor(V1, 1 * meter / second)
|
||||
A1 = Quantity('A1')
|
||||
SI.set_quantity_dimension(A1, acceleration)
|
||||
SI.set_quantity_scale_factor(A1, 1 * meter / second**2)
|
||||
T1 = Quantity('T1')
|
||||
SI.set_quantity_dimension(T1, time)
|
||||
SI.set_quantity_scale_factor(T1, 1 * second)
|
||||
|
||||
expr = A1*T1 + V1
|
||||
# should not throw ValueError here
|
||||
SI._collect_factor_and_dimension(expr)
|
||||
|
||||
|
||||
def test_prefixed_property():
|
||||
assert not meter.is_prefixed
|
||||
assert not joule.is_prefixed
|
||||
assert not day.is_prefixed
|
||||
assert not second.is_prefixed
|
||||
assert not volt.is_prefixed
|
||||
assert not ohm.is_prefixed
|
||||
assert centimeter.is_prefixed
|
||||
assert kilometer.is_prefixed
|
||||
assert kilogram.is_prefixed
|
||||
assert pebibyte.is_prefixed
|
||||
|
||||
def test_physics_constant():
|
||||
from sympy.physics.units import definitions
|
||||
|
||||
for name in dir(definitions):
|
||||
quantity = getattr(definitions, name)
|
||||
if not isinstance(quantity, Quantity):
|
||||
continue
|
||||
if name.endswith('_constant'):
|
||||
assert isinstance(quantity, PhysicalConstant), f"{quantity} must be PhysicalConstant, but is {type(quantity)}"
|
||||
assert quantity.is_physical_constant, f"{name} is not marked as physics constant when it should be"
|
||||
|
||||
for const in [gravitational_constant, molar_gas_constant, vacuum_permittivity, speed_of_light, elementary_charge]:
|
||||
assert isinstance(const, PhysicalConstant), f"{const} must be PhysicalConstant, but is {type(const)}"
|
||||
assert const.is_physical_constant, f"{const} is not marked as physics constant when it should be"
|
||||
|
||||
assert not meter.is_physical_constant
|
||||
assert not joule.is_physical_constant
|
||||
@@ -0,0 +1,55 @@
|
||||
from sympy.concrete.tests.test_sums_products import NS
|
||||
|
||||
from sympy.core.singleton import S
|
||||
from sympy.functions.elementary.miscellaneous import sqrt
|
||||
from sympy.physics.units import convert_to, coulomb_constant, elementary_charge, gravitational_constant, planck
|
||||
from sympy.physics.units.definitions.unit_definitions import angstrom, statcoulomb, coulomb, second, gram, centimeter, erg, \
|
||||
newton, joule, dyne, speed_of_light, meter, farad, henry, statvolt, volt, ohm
|
||||
from sympy.physics.units.systems import SI
|
||||
from sympy.physics.units.systems.cgs import cgs_gauss
|
||||
|
||||
|
||||
def test_conversion_to_from_si():
|
||||
assert convert_to(statcoulomb, coulomb, cgs_gauss) == coulomb/2997924580
|
||||
assert convert_to(coulomb, statcoulomb, cgs_gauss) == 2997924580*statcoulomb
|
||||
assert convert_to(statcoulomb, sqrt(gram*centimeter**3)/second, cgs_gauss) == centimeter**(S(3)/2)*sqrt(gram)/second
|
||||
assert convert_to(coulomb, sqrt(gram*centimeter**3)/second, cgs_gauss) == 2997924580*centimeter**(S(3)/2)*sqrt(gram)/second
|
||||
|
||||
# SI units have an additional base unit, no conversion in case of electromagnetism:
|
||||
assert convert_to(coulomb, statcoulomb, SI) == coulomb
|
||||
assert convert_to(statcoulomb, coulomb, SI) == statcoulomb
|
||||
|
||||
# SI without electromagnetism:
|
||||
assert convert_to(erg, joule, SI) == joule/10**7
|
||||
assert convert_to(erg, joule, cgs_gauss) == joule/10**7
|
||||
assert convert_to(joule, erg, SI) == 10**7*erg
|
||||
assert convert_to(joule, erg, cgs_gauss) == 10**7*erg
|
||||
|
||||
|
||||
assert convert_to(dyne, newton, SI) == newton/10**5
|
||||
assert convert_to(dyne, newton, cgs_gauss) == newton/10**5
|
||||
assert convert_to(newton, dyne, SI) == 10**5*dyne
|
||||
assert convert_to(newton, dyne, cgs_gauss) == 10**5*dyne
|
||||
|
||||
|
||||
def test_cgs_gauss_convert_constants():
|
||||
|
||||
assert convert_to(speed_of_light, centimeter/second, cgs_gauss) == 29979245800*centimeter/second
|
||||
|
||||
assert convert_to(coulomb_constant, 1, cgs_gauss) == 1
|
||||
assert convert_to(coulomb_constant, newton*meter**2/coulomb**2, cgs_gauss) == 22468879468420441*meter**2*newton/(2500000*coulomb**2)
|
||||
assert convert_to(coulomb_constant, newton*meter**2/coulomb**2, SI) == 22468879468420441*meter**2*newton/(2500000*coulomb**2)
|
||||
assert convert_to(coulomb_constant, dyne*centimeter**2/statcoulomb**2, cgs_gauss) == centimeter**2*dyne/statcoulomb**2
|
||||
assert convert_to(coulomb_constant, 1, SI) == coulomb_constant
|
||||
assert NS(convert_to(coulomb_constant, newton*meter**2/coulomb**2, SI)) == '8987551787.36818*meter**2*newton/coulomb**2'
|
||||
|
||||
assert convert_to(elementary_charge, statcoulomb, cgs_gauss)
|
||||
assert convert_to(angstrom, centimeter, cgs_gauss) == 1*centimeter/10**8
|
||||
assert convert_to(gravitational_constant, dyne*centimeter**2/gram**2, cgs_gauss)
|
||||
assert NS(convert_to(planck, erg*second, cgs_gauss)) == '6.62607015e-27*erg*second'
|
||||
|
||||
spc = 25000*second/(22468879468420441*centimeter)
|
||||
assert convert_to(ohm, second/centimeter, cgs_gauss) == spc
|
||||
assert convert_to(henry, second**2/centimeter, cgs_gauss) == spc*second
|
||||
assert convert_to(volt, statvolt, cgs_gauss) == 10**6*statvolt/299792458
|
||||
assert convert_to(farad, centimeter, cgs_gauss) == 299792458**2*centimeter/10**5
|
||||
@@ -0,0 +1,86 @@
|
||||
from sympy.physics.units import DimensionSystem, joule, second, ampere
|
||||
|
||||
from sympy.core.numbers import Rational
|
||||
from sympy.core.singleton import S
|
||||
from sympy.physics.units.definitions import c, kg, m, s
|
||||
from sympy.physics.units.definitions.dimension_definitions import length, time
|
||||
from sympy.physics.units.quantities import Quantity
|
||||
from sympy.physics.units.unitsystem import UnitSystem
|
||||
from sympy.physics.units.util import convert_to
|
||||
|
||||
|
||||
def test_definition():
|
||||
# want to test if the system can have several units of the same dimension
|
||||
dm = Quantity("dm")
|
||||
base = (m, s)
|
||||
# base_dim = (m.dimension, s.dimension)
|
||||
ms = UnitSystem(base, (c, dm), "MS", "MS system")
|
||||
ms.set_quantity_dimension(dm, length)
|
||||
ms.set_quantity_scale_factor(dm, Rational(1, 10))
|
||||
|
||||
assert set(ms._base_units) == set(base)
|
||||
assert set(ms._units) == {m, s, c, dm}
|
||||
# assert ms._units == DimensionSystem._sort_dims(base + (velocity,))
|
||||
assert ms.name == "MS"
|
||||
assert ms.descr == "MS system"
|
||||
|
||||
|
||||
def test_str_repr():
|
||||
assert str(UnitSystem((m, s), name="MS")) == "MS"
|
||||
assert str(UnitSystem((m, s))) == "UnitSystem((meter, second))"
|
||||
|
||||
assert repr(UnitSystem((m, s))) == "<UnitSystem: (%s, %s)>" % (m, s)
|
||||
|
||||
|
||||
def test_convert_to():
|
||||
A = Quantity("A")
|
||||
A.set_global_relative_scale_factor(S.One, ampere)
|
||||
|
||||
Js = Quantity("Js")
|
||||
Js.set_global_relative_scale_factor(S.One, joule*second)
|
||||
|
||||
mksa = UnitSystem((m, kg, s, A), (Js,))
|
||||
assert convert_to(Js, mksa._base_units) == m**2*kg*s**-1/1000
|
||||
|
||||
|
||||
def test_extend():
|
||||
ms = UnitSystem((m, s), (c,))
|
||||
Js = Quantity("Js")
|
||||
Js.set_global_relative_scale_factor(1, joule*second)
|
||||
mks = ms.extend((kg,), (Js,))
|
||||
|
||||
res = UnitSystem((m, s, kg), (c, Js))
|
||||
assert set(mks._base_units) == set(res._base_units)
|
||||
assert set(mks._units) == set(res._units)
|
||||
|
||||
|
||||
def test_dim():
|
||||
dimsys = UnitSystem((m, kg, s), (c,))
|
||||
assert dimsys.dim == 3
|
||||
|
||||
|
||||
def test_is_consistent():
|
||||
dimension_system = DimensionSystem([length, time])
|
||||
us = UnitSystem([m, s], dimension_system=dimension_system)
|
||||
assert us.is_consistent == True
|
||||
|
||||
|
||||
def test_get_units_non_prefixed():
|
||||
from sympy.physics.units import volt, ohm
|
||||
unit_system = UnitSystem.get_unit_system("SI")
|
||||
units = unit_system.get_units_non_prefixed()
|
||||
for prefix in ["giga", "tera", "peta", "exa", "zetta", "yotta", "kilo", "hecto", "deca", "deci", "centi", "milli", "micro", "nano", "pico", "femto", "atto", "zepto", "yocto"]:
|
||||
for unit in units:
|
||||
assert isinstance(unit, Quantity), f"{unit} must be a Quantity, not {type(unit)}"
|
||||
assert not unit.is_prefixed, f"{unit} is marked as prefixed"
|
||||
assert not unit.is_physical_constant, f"{unit} is marked as physics constant"
|
||||
assert not unit.name.name.startswith(prefix), f"Unit {unit.name} has prefix {prefix}"
|
||||
assert volt in units
|
||||
assert ohm in units
|
||||
|
||||
def test_derived_units_must_exist_in_unit_system():
|
||||
for unit_system in UnitSystem._unit_systems.values():
|
||||
for preferred_unit in unit_system.derived_units.values():
|
||||
units = preferred_unit.atoms(Quantity)
|
||||
for unit in units:
|
||||
assert unit in unit_system._units, f"Unit {unit} is not in unit system {unit_system}"
|
||||
@@ -0,0 +1,178 @@
|
||||
from sympy.core.containers import Tuple
|
||||
from sympy.core.numbers import pi
|
||||
from sympy.core.power import Pow
|
||||
from sympy.core.symbol import symbols
|
||||
from sympy.core.sympify import sympify
|
||||
from sympy.printing.str import sstr
|
||||
from sympy.physics.units import (
|
||||
G, centimeter, coulomb, day, degree, gram, hbar, hour, inch, joule, kelvin,
|
||||
kilogram, kilometer, length, meter, mile, minute, newton, planck,
|
||||
planck_length, planck_mass, planck_temperature, planck_time, radians,
|
||||
second, speed_of_light, steradian, time, km)
|
||||
from sympy.physics.units.util import convert_to, check_dimensions
|
||||
from sympy.testing.pytest import raises
|
||||
from sympy.functions.elementary.miscellaneous import sqrt
|
||||
|
||||
|
||||
def NS(e, n=15, **options):
|
||||
return sstr(sympify(e).evalf(n, **options), full_prec=True)
|
||||
|
||||
|
||||
L = length
|
||||
T = time
|
||||
|
||||
|
||||
def test_dim_simplify_add():
|
||||
# assert Add(L, L) == L
|
||||
assert L + L == L
|
||||
|
||||
|
||||
def test_dim_simplify_mul():
|
||||
# assert Mul(L, T) == L*T
|
||||
assert L*T == L*T
|
||||
|
||||
|
||||
def test_dim_simplify_pow():
|
||||
assert Pow(L, 2) == L**2
|
||||
|
||||
|
||||
def test_dim_simplify_rec():
|
||||
# assert Mul(Add(L, L), T) == L*T
|
||||
assert (L + L) * T == L*T
|
||||
|
||||
|
||||
def test_convert_to_quantities():
|
||||
assert convert_to(3, meter) == 3
|
||||
|
||||
assert convert_to(mile, kilometer) == 25146*kilometer/15625
|
||||
assert convert_to(meter/second, speed_of_light) == speed_of_light/299792458
|
||||
assert convert_to(299792458*meter/second, speed_of_light) == speed_of_light
|
||||
assert convert_to(2*299792458*meter/second, speed_of_light) == 2*speed_of_light
|
||||
assert convert_to(speed_of_light, meter/second) == 299792458*meter/second
|
||||
assert convert_to(2*speed_of_light, meter/second) == 599584916*meter/second
|
||||
assert convert_to(day, second) == 86400*second
|
||||
assert convert_to(2*hour, minute) == 120*minute
|
||||
assert convert_to(mile, meter) == 201168*meter/125
|
||||
assert convert_to(mile/hour, kilometer/hour) == 25146*kilometer/(15625*hour)
|
||||
assert convert_to(3*newton, meter/second) == 3*newton
|
||||
assert convert_to(3*newton, kilogram*meter/second**2) == 3*meter*kilogram/second**2
|
||||
assert convert_to(kilometer + mile, meter) == 326168*meter/125
|
||||
assert convert_to(2*kilometer + 3*mile, meter) == 853504*meter/125
|
||||
assert convert_to(inch**2, meter**2) == 16129*meter**2/25000000
|
||||
assert convert_to(3*inch**2, meter) == 48387*meter**2/25000000
|
||||
assert convert_to(2*kilometer/hour + 3*mile/hour, meter/second) == 53344*meter/(28125*second)
|
||||
assert convert_to(2*kilometer/hour + 3*mile/hour, centimeter/second) == 213376*centimeter/(1125*second)
|
||||
assert convert_to(kilometer * (mile + kilometer), meter) == 2609344 * meter ** 2
|
||||
|
||||
assert convert_to(steradian, coulomb) == steradian
|
||||
assert convert_to(radians, degree) == 180*degree/pi
|
||||
assert convert_to(radians, [meter, degree]) == 180*degree/pi
|
||||
assert convert_to(pi*radians, degree) == 180*degree
|
||||
assert convert_to(pi, degree) == 180*degree
|
||||
|
||||
# https://github.com/sympy/sympy/issues/26263
|
||||
assert convert_to(sqrt(meter**2 + meter**2.0), meter) == sqrt(meter**2 + meter**2.0)
|
||||
assert convert_to((meter**2 + meter**2.0)**2, meter) == (meter**2 + meter**2.0)**2
|
||||
|
||||
|
||||
def test_convert_to_tuples_of_quantities():
|
||||
from sympy.core.symbol import symbols
|
||||
|
||||
alpha, beta = symbols('alpha beta')
|
||||
|
||||
assert convert_to(speed_of_light, [meter, second]) == 299792458 * meter / second
|
||||
assert convert_to(speed_of_light, (meter, second)) == 299792458 * meter / second
|
||||
assert convert_to(speed_of_light, Tuple(meter, second)) == 299792458 * meter / second
|
||||
assert convert_to(joule, [meter, kilogram, second]) == kilogram*meter**2/second**2
|
||||
assert convert_to(joule, [centimeter, gram, second]) == 10000000*centimeter**2*gram/second**2
|
||||
assert convert_to(299792458*meter/second, [speed_of_light]) == speed_of_light
|
||||
assert convert_to(speed_of_light / 2, [meter, second, kilogram]) == meter/second*299792458 / 2
|
||||
# This doesn't make physically sense, but let's keep it as a conversion test:
|
||||
assert convert_to(2 * speed_of_light, [meter, second, kilogram]) == 2 * 299792458 * meter / second
|
||||
assert convert_to(G, [G, speed_of_light, planck]) == 1.0*G
|
||||
|
||||
assert NS(convert_to(meter, [G, speed_of_light, hbar]), n=7) == '6.187142e+34*gravitational_constant**0.5000000*hbar**0.5000000/speed_of_light**1.500000'
|
||||
assert NS(convert_to(planck_mass, kilogram), n=7) == '2.176434e-8*kilogram'
|
||||
assert NS(convert_to(planck_length, meter), n=7) == '1.616255e-35*meter'
|
||||
assert NS(convert_to(planck_time, second), n=6) == '5.39125e-44*second'
|
||||
assert NS(convert_to(planck_temperature, kelvin), n=7) == '1.416784e+32*kelvin'
|
||||
assert NS(convert_to(convert_to(meter, [G, speed_of_light, planck]), meter), n=10) == '1.000000000*meter'
|
||||
|
||||
# similar to https://github.com/sympy/sympy/issues/26263
|
||||
assert convert_to(sqrt(meter**2 + second**2.0), [meter, second]) == sqrt(meter**2 + second**2.0)
|
||||
assert convert_to((meter**2 + second**2.0)**2, [meter, second]) == (meter**2 + second**2.0)**2
|
||||
|
||||
# similar to https://github.com/sympy/sympy/issues/21463
|
||||
assert convert_to(1/(beta*meter + meter), 1/meter) == 1/(beta*meter + meter)
|
||||
assert convert_to(1/(beta*meter + alpha*meter), 1/kilometer) == (1/(kilometer*beta/1000 + alpha*kilometer/1000))
|
||||
|
||||
def test_eval_simplify():
|
||||
from sympy.physics.units import cm, mm, km, m, K, kilo
|
||||
from sympy.core.symbol import symbols
|
||||
|
||||
x, y = symbols('x y')
|
||||
|
||||
assert (cm/mm).simplify() == 10
|
||||
assert (km/m).simplify() == 1000
|
||||
assert (km/cm).simplify() == 100000
|
||||
assert (10*x*K*km**2/m/cm).simplify() == 1000000000*x*kelvin
|
||||
assert (cm/km/m).simplify() == 1/(10000000*centimeter)
|
||||
|
||||
assert (3*kilo*meter).simplify() == 3000*meter
|
||||
assert (4*kilo*meter/(2*kilometer)).simplify() == 2
|
||||
assert (4*kilometer**2/(kilo*meter)**2).simplify() == 4
|
||||
|
||||
|
||||
def test_quantity_simplify():
|
||||
from sympy.physics.units.util import quantity_simplify
|
||||
from sympy.physics.units import kilo, foot
|
||||
from sympy.core.symbol import symbols
|
||||
|
||||
x, y = symbols('x y')
|
||||
|
||||
assert quantity_simplify(x*(8*kilo*newton*meter + y)) == x*(8000*meter*newton + y)
|
||||
assert quantity_simplify(foot*inch*(foot + inch)) == foot**2*(foot + foot/12)/12
|
||||
assert quantity_simplify(foot*inch*(foot*foot + inch*(foot + inch))) == foot**2*(foot**2 + foot/12*(foot + foot/12))/12
|
||||
assert quantity_simplify(2**(foot/inch*kilo/1000)*inch) == 4096*foot/12
|
||||
assert quantity_simplify(foot**2*inch + inch**2*foot) == 13*foot**3/144
|
||||
|
||||
def test_quantity_simplify_across_dimensions():
|
||||
from sympy.physics.units.util import quantity_simplify
|
||||
from sympy.physics.units import ampere, ohm, volt, joule, pascal, farad, second, watt, siemens, henry, tesla, weber, hour, newton
|
||||
|
||||
assert quantity_simplify(ampere*ohm, across_dimensions=True, unit_system="SI") == volt
|
||||
assert quantity_simplify(6*ampere*ohm, across_dimensions=True, unit_system="SI") == 6*volt
|
||||
assert quantity_simplify(volt/ampere, across_dimensions=True, unit_system="SI") == ohm
|
||||
assert quantity_simplify(volt/ohm, across_dimensions=True, unit_system="SI") == ampere
|
||||
assert quantity_simplify(joule/meter**3, across_dimensions=True, unit_system="SI") == pascal
|
||||
assert quantity_simplify(farad*ohm, across_dimensions=True, unit_system="SI") == second
|
||||
assert quantity_simplify(joule/second, across_dimensions=True, unit_system="SI") == watt
|
||||
assert quantity_simplify(meter**3/second, across_dimensions=True, unit_system="SI") == meter**3/second
|
||||
assert quantity_simplify(joule/second, across_dimensions=True, unit_system="SI") == watt
|
||||
|
||||
assert quantity_simplify(joule/coulomb, across_dimensions=True, unit_system="SI") == volt
|
||||
assert quantity_simplify(volt/ampere, across_dimensions=True, unit_system="SI") == ohm
|
||||
assert quantity_simplify(ampere/volt, across_dimensions=True, unit_system="SI") == siemens
|
||||
assert quantity_simplify(coulomb/volt, across_dimensions=True, unit_system="SI") == farad
|
||||
assert quantity_simplify(volt*second/ampere, across_dimensions=True, unit_system="SI") == henry
|
||||
assert quantity_simplify(volt*second/meter**2, across_dimensions=True, unit_system="SI") == tesla
|
||||
assert quantity_simplify(joule/ampere, across_dimensions=True, unit_system="SI") == weber
|
||||
|
||||
assert quantity_simplify(5*kilometer/hour, across_dimensions=True, unit_system="SI") == 25*meter/(18*second)
|
||||
assert quantity_simplify(5*kilogram*meter/second**2, across_dimensions=True, unit_system="SI") == 5*newton
|
||||
|
||||
def test_check_dimensions():
|
||||
x = symbols('x')
|
||||
assert check_dimensions(inch + x) == inch + x
|
||||
assert check_dimensions(length + x) == length + x
|
||||
# after subs we get 2*length; check will clear the constant
|
||||
assert check_dimensions((length + x).subs(x, length)) == length
|
||||
assert check_dimensions(newton*meter + joule) == joule + meter*newton
|
||||
raises(ValueError, lambda: check_dimensions(inch + 1))
|
||||
raises(ValueError, lambda: check_dimensions(length + 1))
|
||||
raises(ValueError, lambda: check_dimensions(length + time))
|
||||
raises(ValueError, lambda: check_dimensions(meter + second))
|
||||
raises(ValueError, lambda: check_dimensions(2 * meter + second))
|
||||
raises(ValueError, lambda: check_dimensions(2 * meter + 3 * second))
|
||||
raises(ValueError, lambda: check_dimensions(1 / second + 1 / meter))
|
||||
raises(ValueError, lambda: check_dimensions(2 * meter*(mile + centimeter) + km))
|
||||
@@ -0,0 +1,204 @@
|
||||
"""
|
||||
Unit system for physical quantities; include definition of constants.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from sympy.core.add import Add
|
||||
from sympy.core.function import (Derivative, Function)
|
||||
from sympy.core.mul import Mul
|
||||
from sympy.core.power import Pow
|
||||
from sympy.core.singleton import S
|
||||
from sympy.physics.units.dimensions import _QuantityMapper
|
||||
from sympy.physics.units.quantities import Quantity
|
||||
|
||||
from .dimensions import Dimension
|
||||
|
||||
|
||||
class UnitSystem(_QuantityMapper):
|
||||
"""
|
||||
UnitSystem represents a coherent set of units.
|
||||
|
||||
A unit system is basically a dimension system with notions of scales. Many
|
||||
of the methods are defined in the same way.
|
||||
|
||||
It is much better if all base units have a symbol.
|
||||
"""
|
||||
|
||||
_unit_systems: dict[str, UnitSystem] = {}
|
||||
|
||||
def __init__(self, base_units, units=(), name="", descr="", dimension_system=None, derived_units: dict[Dimension, Quantity]={}):
|
||||
|
||||
UnitSystem._unit_systems[name] = self
|
||||
|
||||
self.name = name
|
||||
self.descr = descr
|
||||
|
||||
self._base_units = base_units
|
||||
self._dimension_system = dimension_system
|
||||
self._units = tuple(set(base_units) | set(units))
|
||||
self._base_units = tuple(base_units)
|
||||
self._derived_units = derived_units
|
||||
|
||||
super().__init__()
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Return the name of the system.
|
||||
|
||||
If it does not exist, then it makes a list of symbols (or names) of
|
||||
the base dimensions.
|
||||
"""
|
||||
|
||||
if self.name != "":
|
||||
return self.name
|
||||
else:
|
||||
return "UnitSystem((%s))" % ", ".join(
|
||||
str(d) for d in self._base_units)
|
||||
|
||||
def __repr__(self):
|
||||
return '<UnitSystem: %s>' % repr(self._base_units)
|
||||
|
||||
def extend(self, base, units=(), name="", description="", dimension_system=None, derived_units: dict[Dimension, Quantity]={}):
|
||||
"""Extend the current system into a new one.
|
||||
|
||||
Take the base and normal units of the current system to merge
|
||||
them to the base and normal units given in argument.
|
||||
If not provided, name and description are overridden by empty strings.
|
||||
"""
|
||||
|
||||
base = self._base_units + tuple(base)
|
||||
units = self._units + tuple(units)
|
||||
|
||||
return UnitSystem(base, units, name, description, dimension_system, {**self._derived_units, **derived_units})
|
||||
|
||||
def get_dimension_system(self):
|
||||
return self._dimension_system
|
||||
|
||||
def get_quantity_dimension(self, unit):
|
||||
qdm = self.get_dimension_system()._quantity_dimension_map
|
||||
if unit in qdm:
|
||||
return qdm[unit]
|
||||
return super().get_quantity_dimension(unit)
|
||||
|
||||
def get_quantity_scale_factor(self, unit):
|
||||
qsfm = self.get_dimension_system()._quantity_scale_factors
|
||||
if unit in qsfm:
|
||||
return qsfm[unit]
|
||||
return super().get_quantity_scale_factor(unit)
|
||||
|
||||
@staticmethod
|
||||
def get_unit_system(unit_system):
|
||||
if isinstance(unit_system, UnitSystem):
|
||||
return unit_system
|
||||
|
||||
if unit_system not in UnitSystem._unit_systems:
|
||||
raise ValueError(
|
||||
"Unit system is not supported. Currently"
|
||||
"supported unit systems are {}".format(
|
||||
", ".join(sorted(UnitSystem._unit_systems))
|
||||
)
|
||||
)
|
||||
|
||||
return UnitSystem._unit_systems[unit_system]
|
||||
|
||||
@staticmethod
|
||||
def get_default_unit_system():
|
||||
return UnitSystem._unit_systems["SI"]
|
||||
|
||||
@property
|
||||
def dim(self):
|
||||
"""
|
||||
Give the dimension of the system.
|
||||
|
||||
That is return the number of units forming the basis.
|
||||
"""
|
||||
return len(self._base_units)
|
||||
|
||||
@property
|
||||
def is_consistent(self):
|
||||
"""
|
||||
Check if the underlying dimension system is consistent.
|
||||
"""
|
||||
# test is performed in DimensionSystem
|
||||
return self.get_dimension_system().is_consistent
|
||||
|
||||
@property
|
||||
def derived_units(self) -> dict[Dimension, Quantity]:
|
||||
return self._derived_units
|
||||
|
||||
def get_dimensional_expr(self, expr):
|
||||
from sympy.physics.units import Quantity
|
||||
if isinstance(expr, Mul):
|
||||
return Mul(*[self.get_dimensional_expr(i) for i in expr.args])
|
||||
elif isinstance(expr, Pow):
|
||||
return self.get_dimensional_expr(expr.base) ** expr.exp
|
||||
elif isinstance(expr, Add):
|
||||
return self.get_dimensional_expr(expr.args[0])
|
||||
elif isinstance(expr, Derivative):
|
||||
dim = self.get_dimensional_expr(expr.expr)
|
||||
for independent, count in expr.variable_count:
|
||||
dim /= self.get_dimensional_expr(independent)**count
|
||||
return dim
|
||||
elif isinstance(expr, Function):
|
||||
args = [self.get_dimensional_expr(arg) for arg in expr.args]
|
||||
if all(i == 1 for i in args):
|
||||
return S.One
|
||||
return expr.func(*args)
|
||||
elif isinstance(expr, Quantity):
|
||||
return self.get_quantity_dimension(expr).name
|
||||
return S.One
|
||||
|
||||
def _collect_factor_and_dimension(self, expr):
|
||||
"""
|
||||
Return tuple with scale factor expression and dimension expression.
|
||||
"""
|
||||
from sympy.physics.units import Quantity
|
||||
if isinstance(expr, Quantity):
|
||||
return expr.scale_factor, expr.dimension
|
||||
elif isinstance(expr, Mul):
|
||||
factor = 1
|
||||
dimension = Dimension(1)
|
||||
for arg in expr.args:
|
||||
arg_factor, arg_dim = self._collect_factor_and_dimension(arg)
|
||||
factor *= arg_factor
|
||||
dimension *= arg_dim
|
||||
return factor, dimension
|
||||
elif isinstance(expr, Pow):
|
||||
factor, dim = self._collect_factor_and_dimension(expr.base)
|
||||
exp_factor, exp_dim = self._collect_factor_and_dimension(expr.exp)
|
||||
if self.get_dimension_system().is_dimensionless(exp_dim):
|
||||
exp_dim = 1
|
||||
return factor ** exp_factor, dim ** (exp_factor * exp_dim)
|
||||
elif isinstance(expr, Add):
|
||||
factor, dim = self._collect_factor_and_dimension(expr.args[0])
|
||||
for addend in expr.args[1:]:
|
||||
addend_factor, addend_dim = \
|
||||
self._collect_factor_and_dimension(addend)
|
||||
if not self.get_dimension_system().equivalent_dims(dim, addend_dim):
|
||||
raise ValueError(
|
||||
'Dimension of "{}" is {}, '
|
||||
'but it should be {}'.format(
|
||||
addend, addend_dim, dim))
|
||||
factor += addend_factor
|
||||
return factor, dim
|
||||
elif isinstance(expr, Derivative):
|
||||
factor, dim = self._collect_factor_and_dimension(expr.args[0])
|
||||
for independent, count in expr.variable_count:
|
||||
ifactor, idim = self._collect_factor_and_dimension(independent)
|
||||
factor /= ifactor**count
|
||||
dim /= idim**count
|
||||
return factor, dim
|
||||
elif isinstance(expr, Function):
|
||||
fds = [self._collect_factor_and_dimension(arg) for arg in expr.args]
|
||||
dims = [Dimension(1) if self.get_dimension_system().is_dimensionless(d[1]) else d[1] for d in fds]
|
||||
return (expr.func(*(f[0] for f in fds)), *dims)
|
||||
elif isinstance(expr, Dimension):
|
||||
return S.One, expr
|
||||
else:
|
||||
return expr, Dimension(1)
|
||||
|
||||
def get_units_non_prefixed(self) -> set[Quantity]:
|
||||
"""
|
||||
Return the units of the system that do not have a prefix.
|
||||
"""
|
||||
return set(filter(lambda u: not u.is_prefixed and not u.is_physical_constant, self._units))
|
||||
@@ -0,0 +1,265 @@
|
||||
"""
|
||||
Several methods to simplify expressions involving unit objects.
|
||||
"""
|
||||
from functools import reduce
|
||||
from collections.abc import Iterable
|
||||
from typing import Optional
|
||||
|
||||
from sympy import default_sort_key
|
||||
from sympy.core.add import Add
|
||||
from sympy.core.containers import Tuple
|
||||
from sympy.core.mul import Mul
|
||||
from sympy.core.power import Pow
|
||||
from sympy.core.sorting import ordered
|
||||
from sympy.core.sympify import sympify
|
||||
from sympy.core.function import Function
|
||||
from sympy.matrices.exceptions import NonInvertibleMatrixError
|
||||
from sympy.physics.units.dimensions import Dimension, DimensionSystem
|
||||
from sympy.physics.units.prefixes import Prefix
|
||||
from sympy.physics.units.quantities import Quantity
|
||||
from sympy.physics.units.unitsystem import UnitSystem
|
||||
from sympy.utilities.iterables import sift
|
||||
|
||||
|
||||
def _get_conversion_matrix_for_expr(expr, target_units, unit_system):
|
||||
from sympy.matrices.dense import Matrix
|
||||
|
||||
dimension_system = unit_system.get_dimension_system()
|
||||
|
||||
expr_dim = Dimension(unit_system.get_dimensional_expr(expr))
|
||||
dim_dependencies = dimension_system.get_dimensional_dependencies(expr_dim, mark_dimensionless=True)
|
||||
target_dims = [Dimension(unit_system.get_dimensional_expr(x)) for x in target_units]
|
||||
canon_dim_units = [i for x in target_dims for i in dimension_system.get_dimensional_dependencies(x, mark_dimensionless=True)]
|
||||
canon_expr_units = set(dim_dependencies)
|
||||
|
||||
if not canon_expr_units.issubset(set(canon_dim_units)):
|
||||
return None
|
||||
|
||||
seen = set()
|
||||
canon_dim_units = [i for i in canon_dim_units if not (i in seen or seen.add(i))]
|
||||
|
||||
camat = Matrix([[dimension_system.get_dimensional_dependencies(i, mark_dimensionless=True).get(j, 0) for i in target_dims] for j in canon_dim_units])
|
||||
exprmat = Matrix([dim_dependencies.get(k, 0) for k in canon_dim_units])
|
||||
|
||||
try:
|
||||
res_exponents = camat.solve(exprmat)
|
||||
except NonInvertibleMatrixError:
|
||||
return None
|
||||
|
||||
return res_exponents
|
||||
|
||||
|
||||
def convert_to(expr, target_units, unit_system="SI"):
|
||||
"""
|
||||
Convert ``expr`` to the same expression with all of its units and quantities
|
||||
represented as factors of ``target_units``, whenever the dimension is compatible.
|
||||
|
||||
``target_units`` may be a single unit/quantity, or a collection of
|
||||
units/quantities.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy.physics.units import speed_of_light, meter, gram, second, day
|
||||
>>> from sympy.physics.units import mile, newton, kilogram, atomic_mass_constant
|
||||
>>> from sympy.physics.units import kilometer, centimeter
|
||||
>>> from sympy.physics.units import gravitational_constant, hbar
|
||||
>>> from sympy.physics.units import convert_to
|
||||
>>> convert_to(mile, kilometer)
|
||||
25146*kilometer/15625
|
||||
>>> convert_to(mile, kilometer).n()
|
||||
1.609344*kilometer
|
||||
>>> convert_to(speed_of_light, meter/second)
|
||||
299792458*meter/second
|
||||
>>> convert_to(day, second)
|
||||
86400*second
|
||||
>>> 3*newton
|
||||
3*newton
|
||||
>>> convert_to(3*newton, kilogram*meter/second**2)
|
||||
3*kilogram*meter/second**2
|
||||
>>> convert_to(atomic_mass_constant, gram)
|
||||
1.660539060e-24*gram
|
||||
|
||||
Conversion to multiple units:
|
||||
|
||||
>>> convert_to(speed_of_light, [meter, second])
|
||||
299792458*meter/second
|
||||
>>> convert_to(3*newton, [centimeter, gram, second])
|
||||
300000*centimeter*gram/second**2
|
||||
|
||||
Conversion to Planck units:
|
||||
|
||||
>>> convert_to(atomic_mass_constant, [gravitational_constant, speed_of_light, hbar]).n()
|
||||
7.62963087839509e-20*hbar**0.5*speed_of_light**0.5/gravitational_constant**0.5
|
||||
|
||||
"""
|
||||
from sympy.physics.units import UnitSystem
|
||||
unit_system = UnitSystem.get_unit_system(unit_system)
|
||||
|
||||
if not isinstance(target_units, (Iterable, Tuple)):
|
||||
target_units = [target_units]
|
||||
|
||||
def handle_Adds(expr):
|
||||
return Add.fromiter(convert_to(i, target_units, unit_system)
|
||||
for i in expr.args)
|
||||
|
||||
if isinstance(expr, Add):
|
||||
return handle_Adds(expr)
|
||||
elif isinstance(expr, Pow) and isinstance(expr.base, Add):
|
||||
return handle_Adds(expr.base) ** expr.exp
|
||||
|
||||
expr = sympify(expr)
|
||||
target_units = sympify(target_units)
|
||||
|
||||
if isinstance(expr, Function):
|
||||
expr = expr.together()
|
||||
|
||||
if not isinstance(expr, Quantity) and expr.has(Quantity):
|
||||
expr = expr.replace(lambda x: isinstance(x, Quantity),
|
||||
lambda x: x.convert_to(target_units, unit_system))
|
||||
|
||||
def get_total_scale_factor(expr):
|
||||
if isinstance(expr, Mul):
|
||||
return reduce(lambda x, y: x * y,
|
||||
[get_total_scale_factor(i) for i in expr.args])
|
||||
elif isinstance(expr, Pow):
|
||||
return get_total_scale_factor(expr.base) ** expr.exp
|
||||
elif isinstance(expr, Quantity):
|
||||
return unit_system.get_quantity_scale_factor(expr)
|
||||
return expr
|
||||
|
||||
depmat = _get_conversion_matrix_for_expr(expr, target_units, unit_system)
|
||||
if depmat is None:
|
||||
return expr
|
||||
|
||||
expr_scale_factor = get_total_scale_factor(expr)
|
||||
return expr_scale_factor * Mul.fromiter(
|
||||
(1/get_total_scale_factor(u)*u)**p for u, p in
|
||||
zip(target_units, depmat))
|
||||
|
||||
|
||||
def quantity_simplify(expr, across_dimensions: bool=False, unit_system=None):
|
||||
"""Return an equivalent expression in which prefixes are replaced
|
||||
with numerical values and all units of a given dimension are the
|
||||
unified in a canonical manner by default. `across_dimensions` allows
|
||||
for units of different dimensions to be simplified together.
|
||||
|
||||
`unit_system` must be specified if `across_dimensions` is True.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy.physics.units.util import quantity_simplify
|
||||
>>> from sympy.physics.units.prefixes import kilo
|
||||
>>> from sympy.physics.units import foot, inch, joule, coulomb
|
||||
>>> quantity_simplify(kilo*foot*inch)
|
||||
250*foot**2/3
|
||||
>>> quantity_simplify(foot - 6*inch)
|
||||
foot/2
|
||||
>>> quantity_simplify(5*joule/coulomb, across_dimensions=True, unit_system="SI")
|
||||
5*volt
|
||||
"""
|
||||
|
||||
if expr.is_Atom or not expr.has(Prefix, Quantity):
|
||||
return expr
|
||||
|
||||
# replace all prefixes with numerical values
|
||||
p = expr.atoms(Prefix)
|
||||
expr = expr.xreplace({p: p.scale_factor for p in p})
|
||||
|
||||
# replace all quantities of given dimension with a canonical
|
||||
# quantity, chosen from those in the expression
|
||||
d = sift(expr.atoms(Quantity), lambda i: i.dimension)
|
||||
for k in d:
|
||||
if len(d[k]) == 1:
|
||||
continue
|
||||
v = list(ordered(d[k]))
|
||||
ref = v[0]/v[0].scale_factor
|
||||
expr = expr.xreplace({vi: ref*vi.scale_factor for vi in v[1:]})
|
||||
|
||||
if across_dimensions:
|
||||
# combine quantities of different dimensions into a single
|
||||
# quantity that is equivalent to the original expression
|
||||
|
||||
if unit_system is None:
|
||||
raise ValueError("unit_system must be specified if across_dimensions is True")
|
||||
|
||||
unit_system = UnitSystem.get_unit_system(unit_system)
|
||||
dimension_system: DimensionSystem = unit_system.get_dimension_system()
|
||||
dim_expr = unit_system.get_dimensional_expr(expr)
|
||||
dim_deps = dimension_system.get_dimensional_dependencies(dim_expr, mark_dimensionless=True)
|
||||
|
||||
target_dimension: Optional[Dimension] = None
|
||||
for ds_dim, ds_dim_deps in dimension_system.dimensional_dependencies.items():
|
||||
if ds_dim_deps == dim_deps:
|
||||
target_dimension = ds_dim
|
||||
break
|
||||
|
||||
if target_dimension is None:
|
||||
# if we can't find a target dimension, we can't do anything. unsure how to handle this case.
|
||||
return expr
|
||||
|
||||
target_unit = unit_system.derived_units.get(target_dimension)
|
||||
if target_unit:
|
||||
expr = convert_to(expr, target_unit, unit_system)
|
||||
|
||||
return expr
|
||||
|
||||
|
||||
def check_dimensions(expr, unit_system="SI"):
|
||||
"""Return expr if units in addends have the same
|
||||
base dimensions, else raise a ValueError."""
|
||||
# the case of adding a number to a dimensional quantity
|
||||
# is ignored for the sake of SymPy core routines, so this
|
||||
# function will raise an error now if such an addend is
|
||||
# found.
|
||||
# Also, when doing substitutions, multiplicative constants
|
||||
# might be introduced, so remove those now
|
||||
|
||||
from sympy.physics.units import UnitSystem
|
||||
unit_system = UnitSystem.get_unit_system(unit_system)
|
||||
|
||||
def addDict(dict1, dict2):
|
||||
"""Merge dictionaries by adding values of common keys and
|
||||
removing keys with value of 0."""
|
||||
dict3 = {**dict1, **dict2}
|
||||
for key, value in dict3.items():
|
||||
if key in dict1 and key in dict2:
|
||||
dict3[key] = value + dict1[key]
|
||||
return {key:val for key, val in dict3.items() if val != 0}
|
||||
|
||||
adds = expr.atoms(Add)
|
||||
DIM_OF = unit_system.get_dimension_system().get_dimensional_dependencies
|
||||
for a in adds:
|
||||
deset = set()
|
||||
for ai in a.args:
|
||||
if ai.is_number:
|
||||
deset.add(())
|
||||
continue
|
||||
dims = []
|
||||
skip = False
|
||||
dimdict = {}
|
||||
for i in Mul.make_args(ai):
|
||||
if i.has(Quantity):
|
||||
i = Dimension(unit_system.get_dimensional_expr(i))
|
||||
if i.has(Dimension):
|
||||
dimdict = addDict(dimdict, DIM_OF(i))
|
||||
elif i.free_symbols:
|
||||
skip = True
|
||||
break
|
||||
dims.extend(dimdict.items())
|
||||
if not skip:
|
||||
deset.add(tuple(sorted(dims, key=default_sort_key)))
|
||||
if len(deset) > 1:
|
||||
raise ValueError(
|
||||
"addends have incompatible dimensions: {}".format(deset))
|
||||
|
||||
# clear multiplicative constants on Dimensions which may be
|
||||
# left after substitution
|
||||
reps = {}
|
||||
for m in expr.atoms(Mul):
|
||||
if any(isinstance(i, Dimension) for i in m.args):
|
||||
reps[m] = m.func(*[
|
||||
i for i in m.args if not i.is_number])
|
||||
|
||||
return expr.xreplace(reps)
|
||||
Reference in New Issue
Block a user