У меня проблемы с получением единиц для чистого упрощения. Программа, которую я пишу, связана с расчетом свойств пружины, требуя 10/11 переменных, контролируемых пользователем, и около дюжины уравнений, все из которых имеют дело со смешанными наборами единиц. Единственной отсутствующей переменной может быть любое из нематериальных свойств (1/5), поэтому я пытаюсь использовать символические уравнения, которые могут решить любую отсутствующую переменную. Я попытался установить переменные с помощью пинты, которая могла правильно уменьшать и не имела этой проблемы, но они не могли правильно Sympify, поэтому мне пришлось вернуться к системе единиц SymPy.
Вот некоторый код, демонстрирующий проблему:
from sympy.physics.units import *
from sympy import pi, sqrt, N, Eq, symbols, solve
lbf=Quantity('lbf', abbrev='lbf')
lbf.set_global_relative_scale_factor((convert_to(pound*acceleration_due_to_gravity,newton))/newton, newton)
F, Y, L, A, m, ns, xi, d = symbols('F Y L A m ns xi d')
ssy, alpha, beta, C = symbols('ssy alpha beta C')
F= 20*lbf
Y= 2*inch
L= 3.25*inch
d= .08*inch
m= .145
A= 201.00
A*=kilo*psi*inch**m
ns= 1.20
xi= .15
eqSsy=Eq(ssy,.45*A/(d**m))
ssy=solve(eqSsy)[0]
eqAlpha=Eq(alpha,eqSsy.rhs/ns)
alpha=solve(eqAlpha)[0]
eqBeta=Eq(beta,(8*(1+xi)*F)/(N(pi)*(d**2)))
beta=solve(eqBeta)[0]
eqC=Eq(C,((2*eqAlpha.rhs-eqBeta.rhs)/(4*eqBeta.rhs))+sqrt((((2*eqAlpha.rhs-eqBeta.rhs)/(4*eqBeta.rhs))**2)-(3*eqAlpha.rhs)/(4*eqBeta.rhs)))
C=solve(eqC)[0]
print(ssy, '\n', alpha, '\n', beta, '\n', C)
Эта проблема не связана с единицей фунт-силы, которую мне пришлось создать, она все еще случалась, когда я использовал необработанные единицы измерения, прежде чем я ее очистил. Это приводит к тому, что C
выходит как 1.62e-28*(3.66645442100299e+28*inch**2*psi - 1.54320987654321e+27*lbf + 3.666454421003e+28*sqrt(-0.252539870841386*inch**2*lbf*psi + (inch**2*psi - 0.0420899784735643*lbf)**2))/lbf
вместо 10.5334875999498
, потому что ни одна из единиц не отменяется в процессе вычисления.
«Исправление» этой проблемы, которого я хочу избежать, заключается в изменении строки 27, создании eqBeta
, я должен жестко преобразовать выходные единицы, чтобы они были в psi
, чтобы единицы измерения не выходили как lbf/inch**2
вместо единицы давления.
eqBeta=Eq(beta,convert_to((8*(1+xi)*F)/(N(pi)*(d**2)),psi))
Можно ли как-нибудь заставить beta
автоматически уменьшаться до соответствующей единицы давления? Входные значения задаются через программу PyQt5, в отличие от этой демонстрации, и им могут быть заданы либо имперские, либо метрические единицы, поэтому я не хочу вручную принудительно преобразовывать в psi
(или принудительно преобразовывать C
в безразмерное) .
Я также был бы признателен, если бы кто-нибудь знал о более чистом или лучшем способе выполнения этих вычислений, поскольку я только что бился головой о SymPy, потому что не нашел другого решения. Эти уравнения и имена переменных взяты из учебника по проектированию машин, и я не хочу вручную создавать пошаговый процесс решения для каждой возможной отсутствующей переменной.
@Davide_sd Я также использую Sympy 1.11.1 и Python 3.9 из-за проблем с PyQT. Вы удалили преобразование единиц измерения или запустили код как есть? Проблемное поведение особенно заметно, когда я меняю eqBeta=Eq(beta,convert_to((8*(1+xi)*F)/(N(pi)*(d**2)),psi))
на eqBeta=Eq(beta,(8*(1+xi)*F)/(N(pi)*(d**2)))
. Код, который я загрузил, содержал «плохое решение», которого я хотел избежать.
Вы можете попробовать перечислить базовые единицы в качестве количеств, которые должны быть сокращены до:
>>> convert_to(C, [kg, meter, second]).n(2)
11.0
Или, если вы не знаете, какие из них использовать,
>>> from sympy.physics.units import UnitSystem
>>> sibase = UnitSystem.get_unit_system("SI")._base_units
>>> convert_to(C, sibase).n(2)
11.0
см этот выпуск
Спасибо! Раньше я пытался получить доступ к базовым единицам, чтобы использовать его таким образом, и сделать мое «автоматическое» сокращение принудительным упрощением базовых единиц в каждом уравнении, но столкнулся с ошибкой, когда он не позволил мне получить к нему доступ. Ошибка по-прежнему отображается в линтере, но, по крайней мере, присвоив ее sibase
, я могу ее использовать. Это не решает всех моих проблем с системой, но, по крайней мере, я думаю, что смогу заставить ее работать в целом.
Какую версию SymPy вы используете? Я использую 1.11.1 и получаю правильный вывод