FEMM 5

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

Собственная четырёхполюсная SPM: полный период, сектор и гармоники ЭДС

Эта машина отличается от 16-полюсного образца AGE: в собственной геометрии курса четыре полюса, 12 пазов и две пары полюсов. Период основной магнитной системы составляет 180 механических градусов. Ротор поворачивается как группа геометрии с перестроением сетки: отсутствующая в файле граница скользящего зазора не имитируется вызовом API.

Сохранённая серия содержит 768 независимо решённых положений за один магнитный период. Подмножества на 48, 96 и 192 точках выделяются из этой серии; они не объявляются дополнительными полевыми решениями.

Место в курсе.Геометрию, физическую постановку и результаты можно изучать вместе с основным занятием. Серийную программу и обработку разбирайте после введения во встроенный 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\). При постоянных магнитах и взаимном возбуждении сначала учитывают ненулевое смещение потокосцепления.
  • Положительные направления, оси и специальные индексы определяются в конкретной задаче. Единицу берите из условия или заголовка таблицы; перед подстановкой в формулу СИ переводите миллиметры в метры, миллигенри в генри и градусы в радианы.
  • Численные результаты обычно показаны с четырьмя значащими цифрами; для сравнения близких значений в таблицах сходимости сохранено больше цифр. Полные значения остаются в исходных расчётных данных. Малые остатки вычисления координат на осях показаны как ноль; малые физические величины сохраняются в показательной записи.

От потокосцепления к ЭДС

Потокосцепление фазы есть сумма потоков всех её витков с учётом знаков сторон обмотки. Для синусоидального вращения удобно сначала определить \Psi (\theta ), затем применить закон Фарадея. При постоянной механической скорости производная по времени равна ωмех, умноженной на производную по углу.

Если k-я электрическая гармоника потокосцепления имеет амплитуду \Psi_k, её частота равна kfэл. Поэтому действующая ЭДС содержит множитель k: малая высокая гармоника потокосцепления может дать заметную гармонику напряжения. Численное дифференцирование шумного ряда без проверки шага опасно.

При исследовании зубцового момента следует анализировать отдельный ненагруженный ряд момента и проверять его гармоники. Сходимость основной ЭДС сама по себе не доказывает сходимость малого зубцового момента.

e(\theta)=-\omega_{\mathrm{мех}}\frac{\mathrm d\Psi}{\mathrm d\theta},\qquad E_{k,\mathrm{д}}=\frac{k\omega_{\mathrm{эл}}\Psi_{k,\mathrm{амп}}}{\sqrt2}
(Р5.1)
Угол в производной выражается в радианах; знак зависит от принятого направления обхода обмотки.
\Psi_{k,\mathrm{амп}}=\frac2N\left|\sum_{j=0}^{N-1}\Psi_j\exp\!\left(-\mathrm i\frac{2\pi kj}{N}\right)\right|
(Р5.2)
Ряд охватывает один электрический период, последняя точка не повторяет первую.

Сектор и два независимых уточнения

Сектор 90^\circ допустим только при согласованной антипериодичности геометрии, намагниченности, витков и текущего возбуждения. Для полной и секторной модели сравнивают одинаковые физические токи и положение; потокосцепление, энергию и момент проверяют отдельно.

Угловое уточнение определяет достоверность спектра, пространственное — точность каждого полевого решения. В дополнительной серии 24 одинаковых угла рассчитаны на сетках зазора 0,4; 0,2; 0,1 мм. Допуск выбирается для конкретной величины до просмотра результата.

Для постоянных магнитов энергия содержит источник намагниченности. Сырой интеграл энергии нельзя бездумно проверять равенством \tfrac12 \Sigma I\Psi: это равенство относится к линейной системе без независимого поля магнитов. В комплекте сохранена специальная проверка энергии возвратной ветви.

\varepsilon_q=\frac{|q_{\mathrm{уточн}}-q_{\mathrm{база}}|}{\max(|q_{\mathrm{уточн}}|,q_{\mathrm{масш}})}
(Р5.3)
Масштаб qмасш необходим около нуля; абсолютный допуск задают заранее.

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

Таблица Р5.1. Исходные данные
ВеличинаЗначениеЕдиница
Пары полюсов2
Пазы12
Положения768
Механический период180{}^\circ
Последний угол179,8{}^\circ
Частота для восстановления ЭДС100Гц
  1. Скачайте опубликованные файлы в одну рабочую папку, сохранив подпапки. Сначала запустите reproduce.py для свежего контрольного поля.
  2. Откройте reference/measurements.json: таблица full_period содержит исходные токи, \Psi трёх фаз, момент и число элементов.
  3. Полные программы, названные далее, запускайте через run-series.py из корня рабочей папки: выберите SERIES_NUMBER по списку README.html. Диспетчер сам устанавливает подпапку и контекст исходной программы; прежний рабочий каталог FEMM не важен.
  4. Запустите reference/postprocess-full.py из его каталога для повторной обработки ряда. Для самостоятельного полного полевого прохода используйте angular-full.py; сектор проверяется sector-full.py.
  5. Сравните \Psi _{1} и гармоники 3, 5, 7, 11 на вложенных подмножествах. Затем отдельно проверьте средний момент на трёх пространственных сетках из дополнительного каталога mesh.
  6. Нарушьте симметрию только в отдельной копии: при несимметричном возбуждении подтвердите необходимость полной геометрии.

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

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

Таблица Р5.2. Численные данные
ОтсчётыΨ₁ фазы А, ВбΨ₃ фазы А, ВбΨ₅ фазы А, Вб
480,34130,029790,007825
960,34130,029790,007827
1920,34130,029790,007826
7680,34130,029790,007825

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

Как воспроизвести в 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. [33]
  2. [59]

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