Электрическое поле тока · Плоскопараллельная
Распределение тока между параллельными полосами
Две параллельные полосы длиной 100 мм и шириной по 10 мм, глубина 1 мм. Общие торцевые электроды соединяют медную и бронзовую области.
Цель работы — связать полевое распределение с измеряемой величиной, получить проверяемый численный результат и объяснить границы выбранной модели. Все параметры заданы непосредственно в программе. Собственная постановка содержит физический ориентир и критерии приёмки, поэтому результат можно исследовать без внешней библиотеки готовых решений.
Самостоятельная учебная модель FEMM 5: от физических соотношений к полевому решению и проверке результата.
Допущения и устройство учебной модели
Все размеры, свойства материалов и условия возбуждения заданы ниже. Численные результаты относятся к опубликованной версии модели FEMM 5.
Физическая и математическая постановка
Теория и контрольная модель
Общее напряжение создаёт одинаковую продольную напряжённость в обеих полосах. При одинаковых геометрических размерах отношение токов равно отношению проводимостей. Электрический контакт по продольной границе допустим: в этой строго симметричной постановке поперечный ток через неё равен нулю.
Медная полоса имеет проводимость в четыре раза выше бронзовой, поэтому принимает 80 процентов общего тока и мощности. Сравнение тока на выводе, групповых интегралов мощности и локальных плотностей тока проверяет один физический вывод тремя способами. Для переменного тока такой вывод уже потребует учёта скин-эффекта и взаимного магнитного поля.
Как читать расчёт и проверки
Программа создаёт три последовательные дискретизации. Для каждой сохраняются отдельная входная модель и собственное решение FEMM. Перед запуском решателя записанный файл закрывается и повторно открывается: проверяется именно сохранённая версия с русскими именами материалов, проводников и границ. В result.json величины records сопровождаются числом узлов и элементов, а checks содержит фактический остаток, предел и логический итог.
Для электрических моделей отдельно проверяются баланс токов на выводах и равенство суммарных джоулевых потерь и активной мощности на выводах. Для тепловых задач используются аналитический профиль, эквивалентное координатное преобразование или интегральный баланс источников и теплоотдачи. Эти проверки отвечают на разные вопросы: совпадение одной температуры или одного тока само по себе не подтверждает правильность всей постановки.
Практическое исследование
Измените ширины полос, сохранив полную ширину 20 мм. Выведите условие равных токов через произведения σw. Проверьте это условие численно и объясните, почему одинаковые токи не означают одинаковые плотности тока.
Переставьте материалы между верхней и нижней областями. При неизменных полных торцевых электродах суммарное сопротивление должно сохраниться. Локальные карты тока должны зеркально поменяться вместе с материалами.
Сравните деление мощности и деление тока. При общем напряжении их доли совпадают. Для неодинаковых подводов и контактов простое отношение проводимостей уже недостаточно; укажите, какие элементы пришлось бы добавить.
Исходные данные
Две параллельные полосы длиной 100 мм и шириной по 10 мм, глубина 1 мм. Общие торцевые электроды соединяют медную и бронзовую области.
| Параметр | Значение | Единица | Происхождение |
|---|---|---|---|
| Длина | 100 | мм | Принято в учебной постановке |
| Ширина каждой ветви | 10 | мм | Принято в учебной постановке |
| Глубина | 1 | мм | Принято в учебной постановке |
| σ меди | 58000000 | См/м | Принято в учебной постановке |
| σ бронзы | 14500000 | См/м | Принято в учебной постановке |
Порядок воспроизведения
- Скопируйте reproduce.py в отдельную рабочую папку и откройте его во встроенном редакторе Python FEMM 5. Запускайте файл целиком. Программа сама создаёт новый каталог calculated-XX рядом с файлом, поэтому повторная серия сохраняет предыдущие модели и результаты.
- До расчёта прочитайте параметры и единицы. После расчёта откройте последнюю входную модель и соответствующее решение. Сопоставьте назначение русских имён с физическим смыслом, определите путь тока или теплового потока и найдите величины, используемые в контрольной формуле.
- Сравните все три записи records и убедитесь, что каждый пункт checks имеет passed=true. Уточните различие между ошибкой аналитического сравнения, изменением по сетке, невязкой баланса и итерационным остатком. Для модели с координатным преобразованием откройте также отдельную контрольную геометрию.
- Выполните исследовательские варианты по одному. Перед изменением предскажите знак и примерный масштаб эффекта. В отчёте приведите выбранные параметры, контрольную формулу, таблицу сеток, независимые проверки и объяснение того, какие выводы можно переносить на реальный объект.
Скачайте нужные файлы по отдельным ссылкам ниже в одну рабочую папку, затем откройте reproduce.py во встроенном Python FEMM 5 и выполните его. Сохраните имена файлов и структуру подпапок. Условия конкретного запуска и путь новых результатов указаны в комментариях программы.
Программа встроенного Python FEMM 5
"""Самостоятельная лабораторная работа курса FEMM 5.
Запуск: встроенный MicroPython FEMM 5, команды FEMM доступны непосредственно.
Геометрические координаты и глубина — мм; результаты интегралов — единицы СИ.
Данные, допущения, аналитические ориентиры и ход исследования заданы в README.md.
Каждая серия записывается в новую calculated-XX; прежние результаты сохраняются.
Сохранённая модель закрывается и открывается до расчёта, включая русские имена.
"""
import os
import sys
import json
import math
script = globals().get("__file__", "") or (sys.argv[0] if sys.argv else "")
base = os.path.dirname(os.path.abspath(script)) if script else os.getcwd()
index = 1
while "calculated-%02d" % index in os.listdir(base):
index += 1
directory = base + "/calculated-%02d" % index
os.mkdir(directory)
records = []
checks = []
def real(value):
if isinstance(value, (tuple, list)):
return real(value[0])
return complex(value).real
def check(name, value, limit):
checks.append(
{
"name": name,
"value": value,
"limit": limit,
"passed": math.isfinite(value) and value <= limit,
}
)
def polygon(prefix, points):
for x, y in points:
globals()[prefix + "_addnode"](x, y)
for i, (x, y) in enumerate(points):
x2, y2 = points[(i + 1) % len(points)]
globals()[prefix + "_addsegment"](x, y, x2, y2)
def geometry(prefix, job, mesh):
if job.get("polygon"):
polygon(prefix, job["polygon"])
for x1, y1, x2, y2 in job.get("interfaces", []):
globals()[prefix + "_addnode"](x1, y1)
globals()[prefix + "_addnode"](x2, y2)
globals()[prefix + "_addsegment"](x1, y1, x2, y2)
for x, y, radius, name in job.get("circles", []):
globals()[prefix + "_addnode"](x - radius, y)
globals()[prefix + "_addnode"](x + radius, y)
globals()[prefix + "_addarc"](x - radius, y, x + radius, y, 180, 1)
globals()[prefix + "_addarc"](x + radius, y, x - radius, y, 180, 1)
globals()[prefix + "_selectarcsegment"](x, y + radius)
globals()[prefix + "_selectarcsegment"](x, y - radius)
if prefix == "ci":
ci_setarcsegmentprop(1, "<None>", 0, 0, name or "<None>")
else:
hi_setarcsegmentprop(1, name or "<None>", 0, 0, "<None>")
globals()[prefix + "_clearselected"]()
for x, y, name, group in job["blocks"]:
globals()[prefix + "_addblocklabel"](x, y)
globals()[prefix + "_selectlabel"](x, y)
globals()[prefix + "_setblockprop"](name, 0, mesh, group)
globals()[prefix + "_clearselected"]()
def current(job, mesh, stem):
newdocument(3)
ci_probdef("millimeters", "planar", 0, 1e-10, job["depth"], 30)
for name, sx, sy in job["materials"]:
ci_addmaterial(name, sx, sy, 1, 1, 0, 0)
for name, voltage, amperes, kind in job["terminals"]:
ci_addconductorprop(name, voltage, amperes, kind)
geometry("ci", job, mesh)
for x, y, name in job.get("electrode_segments", []):
ci_selectsegment(x, y)
ci_setsegmentprop("<None>", mesh, 0, 0, 0, name)
ci_clearselected()
path = directory + "/" + stem + ".fec"
ci_saveas(path)
ci_close()
opendocument(path)
ci_analyze(1)
ci_loadsolution()
co_smooth("off")
terminals = {}
terminal_power = 0
balance = 0
current_scale = 0
for name, voltage, amperes, kind in job["terminals"]:
u, i = co_getconductorproperties(name)
terminals[name] = {"U_V": real(u), "I_A": real(i)}
terminal_power += real(complex(u) * complex(i).conjugate())
balance += complex(i)
current_scale = max(current_scale, abs(complex(i)))
powers = {}
power = 0
for x, y, name, group in job["blocks"]:
if name == "<No Mesh>":
continue
co_groupselectblock(group)
powers[str(group)] = real(co_blockintegral(0))
power += powers[str(group)]
co_clearblock()
samples = []
for x, y in job.get("samples", []):
values = co_getpointvalues(x, y)
samples.append(
{
"x_mm": x,
"y_mm": y,
"U_V": real(values[0]),
"J_A_m2": math.sqrt(
abs(complex(values[1])) ** 2 + abs(complex(values[2])) ** 2
),
}
)
row = {
"model": stem + ".fec",
"mesh_mm": mesh,
"nodes": co_numnodes(),
"elements": co_numelements(),
"terminals": terminals,
"P_W": power,
"group_power_W": powers,
"samples": samples,
"current_balance_relative": abs(balance) / current_scale,
"power_balance_relative": abs(power - terminal_power) / max(power, 1e-30),
}
check(stem + ": баланс токов", row["current_balance_relative"], 1e-6)
check(stem + ": баланс мощности", row["power_balance_relative"], 1e-6)
co_close()
ci_close()
return row
def heat(job, mesh, stem):
newdocument(2)
hi_probdef("millimeters", "planar", 1e-10, job["depth"], 30)
for name, kx, ky, q in job["materials"]:
hi_addmaterial(name, kx, ky, q, 0)
for name, kind, temp, ambient, h in job["boundaries"]:
hi_addboundprop(name, kind, temp, 0, ambient, h, 0)
geometry("hi", job, mesh)
for x, y, name in job.get("boundary_segments", []):
hi_selectsegment(x, y)
hi_setsegmentprop(name, mesh, 0, 0, 0, "<None>")
hi_clearselected()
path = directory + "/" + stem + ".feh"
hi_saveas(path)
hi_close()
opendocument(path)
hi_analyze(1)
hi_loadsolution()
ho_smooth("off")
averages = {}
generated = 0
for x, y, name, group in job["blocks"]:
ho_groupselectblock(group)
averages[str(group)] = real(ho_blockintegral(0))
volume = real(ho_blockintegral(2))
q = [m[3] for m in job["materials"] if m[0] == name][0]
generated += q * volume
ho_clearblock()
samples = []
for x, y in job.get("samples", []):
samples.append({"x_mm": x, "y_mm": y, "T_K": real(ho_getpointvalues(x, y)[0])})
convection = 0
for x1, y1, x2, y2, ambient, h in job.get("convection_edges", []):
count = 200
total = 0
for n in range(count + 1):
t = real(
ho_getpointvalues(
x1 + (x2 - x1) * n / count, y1 + (y2 - y1) * n / count
)[0]
)
total += (0.5 if n in (0, count) else 1) * (t - ambient)
length = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) * 0.001
convection += total / count * length * job["depth"] * 0.001 * h
row = {
"model": stem + ".feh",
"mesh_mm": mesh,
"nodes": ho_numnodes(),
"elements": ho_numelements(),
"samples": samples,
"group_average_K": averages,
"generated_W": generated,
"convection_W": convection,
}
if job.get("convection_edges"):
check(
stem + ": баланс конвективного теплоотвода",
abs(convection - generated) / max(generated, 1e-30),
0.005,
)
ho_close()
hi_close()
return row
JOB = json.loads(
'{"polygon": [[0, 0], [100, 0], [100, 20], [0, 20]], "depth": 1, "materials": [["Медная ветвь", 58000000.0, 58000000.0], ["Бронзовая ветвь", 14500000.0, 14500000.0]], "blocks": [[50, 5, "Медная ветвь", 1], [50, 15, "Бронзовая ветвь", 2]], "terminals": [["Питание", 0.01, 0, 1], ["Возврат", 0, 0, 1]], "electrode_segments": [[0, 5, "Питание"], [0, 15, "Питание"], [100, 5, "Возврат"], [100, 15, "Возврат"]], "samples": [[50, 5], [50, 15]], "interfaces": [[0, 10, 100, 10]]}'
)
for level, mesh in enumerate((1, 0.5, 0.25)):
row = current(JOB, mesh, "model-%02d" % (level + 1))
row["R_ohm"] = 0.01 / abs(row["terminals"]["Питание"]["I_A"])
row["copper_power_fraction"] = row["group_power_W"]["1"] / row["P_W"]
row["J_ratio"] = row["samples"][0]["J_A_m2"] / row["samples"][1]["J_A_m2"]
records.append(row)
reference = 0.1 / ((5.8e7 + 1.45e7) * 0.01 * 0.001)
check("Параллельная проводимость", abs(records[-1]["R_ohm"] / reference - 1), 1e-6)
check(
"Доля тока и мощности медной полосы",
abs(records[-1]["copper_power_fraction"] - 0.8),
1e-6,
)
check("Отношение плотностей тока", abs(records[-1]["J_ratio"] / 4 - 1), 1e-6)
result = {
"runtime": "FEMM 5; embedded MicroPython",
"records": records,
"checks": checks,
"passed": all(item["passed"] for item in checks),
}
with open(directory + "/result.json", "w") as output:
json.dump(result, output)
print(json.dumps(result))
assert result["passed"]
Картина рассчитанного поля
Окна FEMM 5
Снимки интерфейса FEMM показывают геометрию, настройки и работу с результатами в FEMM 5. Откройте изображение, чтобы рассмотреть подписи и значения в полном размере.
Результаты и численные проверки
Сохранено решений FEMM: 3. Выполнено проверок: 9. Полная точность чисел и условия сравнения доступны в таблицах результатов JSON.
| Доля мощности в меди | Контрольные точки | Электроды | Модель | Отношение плотностей тока | Сопротивление, Ом | Узлов | Относительная невязка тока | Относительная невязка мощности | Мощность, Вт | Мощность области, Вт | Элементов | Масштаб сетки, мм |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0,8 | 2 точек; полные данные JSON | 2 полей; полные данные JSON | model-01.fec | 4 | 137,93103 × 10⁻⁶ | 2509 | 2,343445 × 10⁻⁹ | 1,0771113 × 10⁻⁹ | 0,725 | 2 полей; полные данные JSON | 4739 | 1 |
| 0,8 | 2 точек; полные данные JSON | 2 полей; полные данные JSON | model-02.fec | 4 | 137,93103 × 10⁻⁶ | 9547 | 9,5194119 × 10⁻⁹ | 6,5714349 × 10⁻⁹ | 0,725 | 2 полей; полные данные JSON | 18557 | 0,5 |
| 0,8 | 2 точек; полные данные JSON | 2 полей; полные данные JSON | model-03.fec | 4,0000002 | 137,93103 × 10⁻⁶ | 37527 | 16,214757 × 10⁻⁹ | 4,1936009 × 10⁻⁹ | 0,725 | 2 полей; полные данные JSON | 73976 | 0,25 |
| Критерий | Получено | Допуск или ожидаемое значение | Итог |
|---|---|---|---|
| model-01: баланс токов | 2,343 × 10⁻⁹ | 1e-06 | Выполнен |
| model-01: баланс мощности | 1,077 × 10⁻⁹ | 1e-06 | Выполнен |
| model-02: баланс токов | 9,519 × 10⁻⁹ | 1e-06 | Выполнен |
| model-02: баланс мощности | 6,571 × 10⁻⁹ | 1e-06 | Выполнен |
| model-03: баланс токов | 16,21 × 10⁻⁹ | 1e-06 | Выполнен |
| model-03: баланс мощности | 4,194 × 10⁻⁹ | 1e-06 | Выполнен |
| Параллельная проводимость | 4,193 × 10⁻⁹ | 1e-06 | Выполнен |
| Доля тока и мощности медной полосы | 888,2 × 10⁻¹⁸ | 1e-06 | Выполнен |
| Отношение плотностей тока | 51,74 × 10⁻⁹ | 1e-06 | Выполнен |
Допуски относятся к указанной учебной задаче и способу сравнения. Число показанных цифр не означает такой же физической точности.
Модели, решения и программа
Для нового расчёта сохраните программу, модели и необходимые данные в одну рабочую папку, сохраняя структуру подпапок.
- Файл результатов: README.md8259 байт
- Решение электрического тока: model-01.anc231834 байт
- Модель электрического тока: model-01.fec1342 байт
- Решение электрического тока: model-02.anc932543 байт
- Модель электрического тока: model-02.fec1354 байт
- Решение электрического тока: model-03.anc3910795 байт
- Модель электрического тока: model-03.fec1360 байт
- Программа встроенного Python: reproduce.py9506 байт
- Файл результатов: verification.json912 байт
Границы применимости
- Постоянный ток, одинаковые температуры, идеальные общие электроды. Не учитываются сопротивления подводов и контактных соединений.
- Проверка выполнена решателем FEMM 5.0 06Oct2026 во встроенной среде MicroPython. Она относится к данной версии геометрии, свойств и численных критериев. Снимки интерфейса FEMM выполняются отдельным согласованным проходом.