Автоматическое уменьшение и отмена единиц с SymPy

У меня проблемы с получением единиц для чистого упрощения. Программа, которую я пишу, связана с расчетом свойств пружины, требуя 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, потому что не нашел другого решения. Эти уравнения и имена переменных взяты из учебника по проектированию машин, и я не хочу вручную создавать пошаговый процесс решения для каждой возможной отсутствующей переменной.

Какую версию SymPy вы используете? Я использую 1.11.1 и получаю правильный вывод

Davide_sd 13.02.2023 09:48

@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))). Код, который я загрузил, содержал «плохое решение», которого я хотел избежать.

UnsweetIceTea 13.02.2023 12:53
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете попробовать перечислить базовые единицы в качестве количеств, которые должны быть сокращены до:

>>> 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, я могу ее использовать. Это не решает всех моих проблем с системой, но, по крайней мере, я думаю, что смогу заставить ее работать в целом.

UnsweetIceTea 13.02.2023 17:33

Другие вопросы по теме