FEMM 5

Исследование 3 · FEMM 5 · встроенный Python

SPM со скользящим зазором: 180 положений, спектры и потери при 80 скоростях

В машине с поверхностными постоянными магнитами поле возбуждения вращается вместе с ротором. Статорная точка видит переменное поле, а точка магнита — почти постоянную основную составляющую и пульсации от пазов. Для оценки потерь нужно различать эти системы отсчёта.

В этом разборе используется готовый пример Meeker, уже перенесённый в настоящий встроенный Python FEMM 5. Здесь 16 магнитных полюсов, а не четыре полюса собственной SPM-модели курса. Граница AGE действительно существует в исходном файле. Проверенные варианты plain и fast выполняют одинаковые полевые задачи; ускорение меняет организацию обработки массивов.

В комплекте используются учебные копии FEMM 5 с русскими именами свойств. Геометрия, источники и численные параметры библиотечного примера сохранены; соответствия имён приведены в teaching-adaptation.json. Библиотечные оригиналы в курс и архив не входят.

Место в курсе.Геометрию, физическую постановку и результаты можно изучать вместе с основным занятием. Серийную программу и обработку разбирайте после введения во встроенный Python.

Объект, физическая модель и вывод соотношений

Соглашения об обозначениях и единицах
  • \(i(t)\), \(u(t)\) — мгновенные значения; \(\widehat I\), \(\widehat U\) — комплексные амплитуды; \(\underline I_{\text{д}}\), \(\underline U_{\text{д}}\) — комплексные действующие значения. Для синусоиды \(\widehat I=\sqrt{2}\,\underline I_{\text{д}}\); действующее значение тока равно \(|\underline I_{\text{д}}|\). Нормировка обязательно учитывается в формулах мощности.
  • \(\Phi=\int_S\mathbf B\cdot\mathrm d\mathbf S\) — поток через ориентированную поверхность; \(\Psi=\sum_k\oint_{C_k}\mathbf A\cdot\mathrm d\mathbf l\) — потокосцепление последовательных витков с согласованными замкнутыми контурами. Только при одинаковом сцепленном потоке каждого витка \(\Psi=N\Phi\). Обе величины измеряются в веберах: число витков безразмерно. Запись «Вб·виток» подчёркивает суммирование.
  • \(\theta_{\text{м}}\), \(\Omega\) (также \(\omega_{\text{мех}}\)) — механические угол и угловая скорость. Для основной гармоники \(\theta_{\text{э}}=p\theta_{\text{м}}\), \(\omega_{\text{э}}=p\Omega\), где \(p\) — число пар полюсов. Геометрический период зубцов задаётся отдельно. В производных по углу используйте радианы.
  • Статическая индуктивность \(L_{\text{ст}}=\Psi/i\) — наклон секущей из начала координат; это определение используется при \(\Psi(0)=0\) и \(i\ne0\). Динамическая индуктивность \(L_{\text{дин}}=\partial\Psi/\partial i\) — наклон касательной (дифференциальная, инкрементальная); положение и остальные токи фиксированы. Для линейной характеристики без смещения обе равны одной индуктивности \(L\). При постоянных магнитах и взаимном возбуждении сначала учитывают ненулевое смещение потокосцепления.
  • Положительные направления, оси и специальные индексы определяются в конкретной задаче. Единицу берите из условия или заголовка таблицы; перед подстановкой в формулу СИ переводите миллиметры в метры, миллигенри в генри и градусы в радианы.
  • Численные результаты обычно показаны с четырьмя значащими цифрами; для сравнения близких значений в таблицах сходимости сохранено больше цифр. Полные значения остаются в исходных расчётных данных. Малые остатки вычисления координат на осях показаны как ноль; малые физические величины сохраняются в показательной записи.

От движения к спектру

Механический угол ротора обозначим \theta. При p парах полюсов электрический угол равен p\theta, поэтому токи синхронного режима задаются функциями p\theta с фазовыми сдвигами 120^\circ. Параметр 10 границы AGE задаёт положение вращающейся стороны зазора. Геометрия и сетка каждого тела остаются неизменными.

Равномерные точки одного периода берутся без повторения последнего конца. Разложение произвольного отсчётного ряда даёт комплексные коэффициенты; для вещественного сигнала амплитуда положительной ненулевой гармоники равна удвоенному модулю коэффициента. Удвоение не применяют к постоянной составляющей и отдельной частоте Найквиста.

Поскольку анализируется механический период 180^\circ, номер k спектральной ячейки соответствует механическому порядку 2k. В обычном геометрическом повороте точки ротора и оси вектора отслеживают вместе с телом. AGE сохраняет локальную сетку вращающейся части; в готовом примере следует сохранять принятую конвенцию координат, не вводя поверх неё второй искусственный поворот.

\theta_{\mathrm{эл}}=p\theta,\qquad f_{\mathrm{эл}}=\frac{pn}{60}
(Р3.1)
p=8; n задаётся в об/мин, частота получается в Гц.
\widehat b_k=\frac1N\sum_{j=0}^{N-1}b_j\exp\!\left(-\mathrm{i}\frac{2\pi kj}{N}\right),\qquad B_{k,\mathrm{амп}}=2|\widehat b_k|
(Р3.2)
Дискретное преобразование Фурье и амплитудная нормировка ненулевой положительной гармоники.

Почему потери зависят от частоты

Энергия гистерезисного цикла рассеивается каждый период, что даёт линейную зависимость мощности от частоты. Для тонкой пластины закон Фарадея даёт вихревое электрическое поле, пропорциональное fB, а закон Джоуля — мощность, пропорциональную f^{2}B^{2}. В примере используются заданные коэффициенты ch и ce; их нельзя переносить на другую сталь без измерений.

Потери постоянного тока в трёх фазах равны 3R Iд². При заданной амплитуде синусоиды Iамп действующий ток равен Iамп/√2. Температура здесь входит в сопротивление меди через заранее выбранный подъём на 100 °С. Потери в магнитах и от эффекта близости восстанавливаются по спектрам отдельно.

Серия 100–8000 об/мин получена масштабированием частот одних полевых спектров. Это 180 магнитостатических решений и 80 постобработанных режимов скорости; 14 400 новых полевых решений не выполнялись.

P_{\mathrm{ст}}=\sum_{e,k}V_e\left(c_{\mathrm{г}}f_k+c_{\mathrm{в}}f_k^2\right)B_{e,k}^2,\qquad P_{\mathrm{медь}}=\frac32R_{\mathrm{ф}}I_{\mathrm{амп}}^2
(Р3.3)
Схематическая запись используемой спектральной модели; точная нормировка и коэффициент заполнения сохраняются в программе.

Точные спектральные суммы исходной программы

В программе сначала для каждой гармоники суммируются по соответствующим группам объёмы элементов, умноженные на сумму квадратов амплитуд B_x и B_y. Ненулевые амплитуды получаются нормировкой 2/N. Частота гармоники механического порядка 2k равна 2kn/60. Постоянная составляющая не создаёт потери в данной частотной модели.

Для отдельно изолированного магнита суммарный продольный ток должен быть нулевым. Из E=-\partial A/\partial t-\nabla \varphi постоянная по сечению градиентная поправка выбирается так, чтобы средний ток исчезал. Для каждой гармоники это эквивалентно вычитанию объёмно-взвешенного среднего A по данному магниту. Закон Джоуля затем даёт множитель σмагω²/2.

В тонком круглом проводе при почти равномерном поперечном поле наведённая продольная напряжённость пропорциональна расстоянию от центра. Средний квадрат этой координаты равен d^{2}/16, а усреднение синусоиды даёт 1/2. Отсюда коэффициент π²d²σkз,медь/8 перед f^{2}B^{2}. При диаметре, сравнимом с глубиной проникновения, это приближение следует заменить полевой моделью проводников.

Заданные ch=143 и ce=0,530 относятся к объёмной модели этого источника. Коэффициент пакета kз=0,95 делит сумму потерь стали. Обмоточный коэффициент заполнения 0,3882, диаметр провода AWG25 и температурная проводимость входят в отдельный коэффициент близости.

S_{g,k}=\sum_{e\in g}V_e\left(|\widehat B_{x,e,k}|^2+|\widehat B_{y,e,k}|^2\right),\quad P_g=\frac1{k_{\mathrm{з}}}\sum_k(c_{\mathrm{г}}f_k+c_{\mathrm{в}}f_k^2)S_{g,k}
(Р3.4)
g отдельно обозначает статорную или роторную сталь. Программа использует положительную половину спектра без повторного зеркального учёта.
\langle\widehat A_k\rangle_m=\frac{\sum_{e\in m}V_e\widehat A_{e,k}}{\sum_{e\in m}V_e},\quad P_{\mathrm{маг}}=\frac{\sigma_{\mathrm{маг}}}2\sum_{m,k}\omega_k^2\sum_{e\in m}V_e|\widehat A_{e,k}-\langle\widehat A_k\rangle_m|^2
(Р3.5)
Вычитание выполняется отдельно для каждого электрически изолированного магнита, а не для всего ротора.
c_{\mathrm{близ}}=\frac{\pi^2d_{\mathrm{пр}}^2\sigma_{\mathrm{медь}}k_{\mathrm{з,медь}}}{8},\qquad P_{\mathrm{близ}}=\sum_k c_{\mathrm{близ}}f_k^2S_{\mathrm{обм},k}
(Р3.6)
Закон относится к заданному приближению тонких круговых проводников. Плотность основного транспортного тока учтена отдельными потерями I^{2}R.

Постановка и последовательность расчёта

Таблица Р3.1. Исходные данные
ВеличинаЗначениеЕдиница
Число пар полюсов8
Механический период180{}^\circ
Шаг ротора1{}^\circ
Амплитуда i_q2А
Число скоростей80
Скорость100…8000об/мин
Коэффициент пакета0,95
  1. Откройте учебную копию reference/my_SPM_motor_AGB.fem и убедитесь, что в списке свойств есть «Скользящий зазор AGE».
  2. Скачайте файлы приложения в новую папку, сохранив имена и структуру подпапок. Основной reproduce.py заново решает контрольное положение и сверяет момент по mo_gapintegral.
  3. Полные программы, названные далее, запускайте через run-series.py из корня рабочей папки: выберите SERIES_NUMBER по списку README.html. Диспетчер сам устанавливает подпапку и контекст исходной программы; прежний рабочий каталог FEMM не важен.
  4. Для полного прохода выполните reference/run-plain.py встроенным Python FEMM 5. Учебный пакетный вариант run_native.py создаёт CSV в новой папке и использует русские имена свойств модели.
  5. Сопоставьте угол, токи и постоянство сетки; затем откройте таблицы torque.csv, spectra.csv и losses.csv. Сначала объясните физический смысл нулевой спектральной составляющей ротора, затем сравните составляющие потерь.
  6. Повторите reference/run-fast.py; совпадение чисел подтверждает эквивалентность обработки данных, а не пространственную сходимость поля.

Численные результаты и их проверка

Показаны сохранённые результаты FEMM 5. Переключатель и курсор исследуют готовую серию; повторный расчёт выполняется программой в установленном FEMM.

Таблица Р3.2. Численные данные
Скорость, об/минРотор, ВтСтатор, ВтМагниты, ВтМедь, ВтБлизость, ВтВсего, Вт
100221,9 × 10⁻⁶0,02928866,9 × 10⁻⁶4,3736,58 × 10⁻⁶4,401
10000,0043160,42920,086694,370,0036584,894
20000,013291,1610,34684,370,014635,906
40000,045223,5351,3874,370,058539,396
80000,16511,925,5484,370,234122,24

Контрольные сопоставления

Как воспроизвести в FEMM 5

Скачайте программу и необходимые модели, данные и инструкции из списка ниже. Сохраните указанные имена файлов и структуру подпапок. Откройте программу в редакторе встроенного Python FEMM 5 и запустите её. Внешний CPython для управления FEMM не требуется.

Скачайте все нужные файлы со страницы исследования в новую папку, сохранив имена и структуру подпапок. Выполните reproduce.py встроенным Python FEMM 5: проверяются хеши, заново решаются контрольные поля и пересчитываются численные проверки таблиц. Рабочий каталог определяется по пути сохранённого сценария. Полные программы запускайте через run-series.py; номер SERIES_NUMBER выбирается по списку в README.html.

Программа встроенного Python

Текст программы
# Выполняется только встроенным Python FEMM 5.
# Распакуйте весь ZIP в новую папку и запустите этот файл через меню Scripts.
# Запускайте сохранённый файл целиком: путь передаётся в sys.argv[0].
import os, sys, json, math, hashlib
assert sys.implementation.name == 'micropython', 'Нужен встроенный Python FEMM 5'
_saved_file = globals().get('__file__') or (sys.argv[0] if sys.argv else '')
assert _saved_file and os.path.isfile(_saved_file), 'Запустите сохранённый файл из полного распакованного комплекта'
os.chdir(os.path.dirname(os.path.abspath(_saved_file)))
with open('manifest.json') as f: manifest = json.load(f)

def digest(path):
    h = hashlib.sha256()
    with open(path, 'rb') as f:
        while True:
            b = f.read(65536)
            if not b: break
            h.update(b)
    return ''.join('%02x' % b for b in h.digest())

# До расчёта проверяем переносимость и неизменность всех приложенных входов.
for item in manifest['files']:
    assert digest(item['path']) == item['sha256'], 'Изменён вход ' + item['path']
with open('expected-native.json') as f: cases = json.load(f)
os.mkdir('reproduced')   # Отказ от перезаписи предыдущего результата намеренный.
out = {'implementation': str(sys.implementation), 'runtime': sys.version,
       'case_id': manifest['case_id'], 'fresh_fields': [], 'checks': []}

def z(v):
    if isinstance(v, dict): return complex(v['re'], v['im'])
    if isinstance(v, (list, tuple)): return complex(v[0], v[1])
    return complex(v)

def serial(v):
    if isinstance(v, complex): return [v.real, v.imag]
    if isinstance(v, (list, tuple)): return [serial(t) for t in v]
    if isinstance(v, dict): return {k: serial(t) for k,t in v.items()}
    return v

def check(label, actual, expected, tolerance):
    error = abs(z(actual) - z(expected))
    out['checks'].append({'name':label,'actual':serial(actual),
                         'expected':serial(expected),'error':error,
                         'tolerance':tolerance,'passed':error <= tolerance})

for j, spec in enumerate(cases):
    for cmd in ('mo_close', 'mi_close'):
        try: globals()[cmd]()
        except Exception: pass
    opendocument(spec['model'])
    mi_saveas('reproduced/control-' + str(j) + '.fem')
    if 'frequency_Hz' in spec:
        mi_probdef(spec['frequency_Hz'], 'millimeters', 'planar', 1e-8,
                   spec.get('depth_mm',100), 20)
    for name,value in spec.get('set_circuits',{}).items():
        mi_modifycircprop(name, 1, z(value))
    if spec.get('rotate_deg'):
        mi_selectgroup(2); mi_moverotate(0,0,spec['rotate_deg'],4); mi_clearselected()
    if 'boundary' in spec:
        name,index,value = spec['boundary']; mi_modifyboundprop(name,index,value)
    mi_saveas('reproduced/control-' + str(j) + '.fem')
    mi_analyze(1); mi_loadsolution(); mo_smooth('off')
    row = {'model':spec['model'],'elements':mo_numelements(),'nodes':mo_numnodes(),
           'problem':serial(mo_getprobleminfo()),'circuits':{}}
    for name, values in spec.get('circuits',{}).items():
        actual = list(mo_getcircuitproperties(name)); row['circuits'][name] = serial(actual)
        for k,expected in enumerate(values):
            check('Поле '+str(j)+' '+name+' '+('I','U','Psi')[k], actual[k], expected,
                  max(1e-9, 1e-5*abs(z(expected))))
    mo_clearblock(); mo_groupselectblock()
    for key,expected in spec.get('integrals',{}).items():
        actual=mo_blockintegral(int(key)); row['integral_'+key]=serial(actual)
        check('Объёмный интеграл '+key,actual,expected,max(1e-7,1e-5*abs(z(expected))))
    mo_clearblock()
    if 'gap_torque' in spec:
        q=spec['gap_torque']; actual=mo_gapintegral(q['name'],0)
        if isinstance(actual,(list,tuple)): actual=actual[0]
        row['gap_torque_Nm']=serial(actual)
        check('Момент границы AGE',actual,q['expected'],q['tolerance'])
    if 'torque' in spec:
        q=spec['torque'];mo_groupselectblock(q['group']);actual=mo_blockintegral(22);mo_clearblock()
        row['torque_Nm']=serial(actual);check('Момент WST',actual,q['expected'],q['tolerance'])
    if 'magnet_probe' in spec:
        # Исходные графические минимумы получены со сглаживанием поля.
        # Настройку сохраняем явно, чтобы сравнивать одинаковые величины.
        mo_smooth('on')
        q=spec['magnet_probe']
        for p in q['extrema']:
            x,y=p['minimum_point_mm'];angle=math.atan2(y,x)
            sign=1 if p['pole']%2==0 else -1;v=mo_getpointvalues(x,y)
            h=(z(v[1]).real*sign*math.cos(angle)+z(v[2]).real*sign*math.sin(angle)-q['Br_T'])/(4*math.pi*1e-7*q['mu'])
            check('Физический H вдоль намагничивания полюса '+str(p['pole']),h,p['Hparallel_min_A_m'],.02)
    out['fresh_fields'].append(row)
    with open('reproduced/native-result.json','w') as f: json.dump(out,f)
    mo_close();mi_close()

# Повторяем предметные арифметические проверки сохранённых серий.
with open('postprocess.py') as f: exec(f.read(),globals())
out['passed']=all(q['passed'] for q in out['checks'])
with open('reproduced/native-result.json','w') as f: json.dump(out,f)
print('AUDIT_CASE',out['case_id'],'FIELDS',len(out['fresh_fields']),
      'CHECKS',len(out['checks']),'PASSED',out['passed'])
assert out['passed'], 'Есть несогласованные численные проверки; см. native-result.json'

Как трактовать результат

Расчётная среда: FEMM 5.0 06Oct2026; встроенный MicroPython; без внешнего Python/COM/TCP

Введение в устройство и принцип действия объекта, вывод учебных соотношений и пояснения к результатам написаны для этого курса. Численные результаты и заимствованные методы связаны с указанными ниже исходными материалами.

Источники и дальнейшее чтение

  1. [59]
  2. [33]

← Все расчётные исследования