Электростатика · Плоскопараллельная
Скругление электрода: интегральная и локальная сходимость
Сравните электроды с тремя радиусами скругления углов. Покажите, что малая погрешность ёмкости ещё не гарантирует точности локальной напряжённости около кромки.
Самостоятельная учебная модель FEMM 5: от физических соотношений к полевому решению и проверке результата.
Допущения и устройство учебной модели
| Учебная модель FEMM 5 | Причина |
|---|---|
| Точные дуги скругления вместо острого угла | Задаётся конечная геометрическая кривизна. |
| Локальное поле и ёмкость имеют отдельные критерии сходимости | Интегральная точность не переносится автоматически на градиент. |
Все размеры, свойства материалов и условия возбуждения заданы ниже. Численные результаты относятся к опубликованной версии модели FEMM 5.
Физическая и математическая постановка
Кривизна и концентрация поля
Электрод занимает квадрат 6×6 мм со скруглёнными углами и расположен внутри кругового заземлённого экрана. Уменьшение радиуса кривизны концентрирует поверхностный заряд около угла и усиливает локальное поле. Строго острый угол заменён конечным радиусом 0,2, 0,5 или 1 мм.
Что именно проверяет локальная проба
Для каждого радиуса выполнены три сетки. Интегральная ёмкость проверяется по энергии и заряду; локальное поле считывается на биссектрисе угла в 0,2 мм от округлённой поверхности. Используется восстановленное сглаженное поле FEMM, и его сеточная устойчивость проверяется отдельно.
Контрольная точка не является поиском глобального максимума E. Сопоставление показывает изменение поля на заданном физическом расстоянии от разных скруглений. Для оценки максимума на поверхности необходимы дополнительный анализ границы и более строгая локальная серия.
Исходные данные
Плоскопараллельная
| Параметр | Значение | Единица | Происхождение |
|---|---|---|---|
| Габарит электрода | 6 × 6 | мм | Условие учебной задачи |
| Радиусы скругления | 0,2; 0,5; 1 | мм | Условие учебной задачи |
| Радиус экрана | 12 | мм | Условие учебной задачи |
| Глубина | 10 | мм | Условие учебной задачи |
| Напряжение | 100 | В | Условие учебной задачи |
| Отступ контрольной точки от угла | 0,2 | мм | Условие учебной задачи |
Порядок воспроизведения
- Изучите размеры, материалы, возбуждение и выбранную двумерную постановку. Сначала вычислите аналитический ориентир в единицах СИ.
- Скачайте файлы по отдельным ссылкам в отдельную рабочую папку. Откройте reproduce.py во встроенном редакторе Python FEMM 5 и выполните сохранённый файл.
- Программа строит русифицированные модели, сохраняет их, закрывает и открывает заново. Затем выполняет расчёт и читает свойства проводников по точному русскому имени.
- Сравните три уровня пространственной сетки. В таблицах сохранены число узлов и элементов, интегральные величины и независимые критерии. Дополнительные режимы указаны в постановке.
- Откройте самый подробный сохранённый вход и соответствующее решение. Проверьте смысл единиц, знаков и объёмного множителя; новый запуск сохранит результаты в новой папке calculated-NN.
Скачайте нужные файлы по отдельным ссылкам ниже в одну рабочую папку, затем откройте reproduce.py во встроенном Python FEMM 5 и выполните его. Сохраните имена файлов и структуру подпапок. Условия конкретного запуска и путь новых результатов указаны в комментариях программы.
Программа встроенного Python FEMM 5
"""Скругление электрода и локальная напряжённость.
Среда: встроенный MicroPython FEMM 5; команды FEMM доступны глобально.
Геометрические размеры: миллиметры; поля и интегралы возвращаются в СИ.
Все материалы и проводники имеют русские имена. Каждая модель сохраняется,
закрывается и повторно открывается до нового расчёта, включая кириллицу.
Запуск создаёт новую папку calculated-NN рядом с программой; опубликованные
модели и предыдущие расчёты не перезаписываются. Все необходимые
исходные данные включены. Условия задачи и ограничения описаны в README.md.
"""
import os
import sys
import math
import json
saved = globals().get('__file__', '') or (sys.argv[0] if sys.argv else '')
base = os.path.dirname(os.path.abspath(saved)) if saved else os.getcwd()
index = 1
while os.path.exists(base + '/calculated-%02d' % index):
index += 1
directory = base + '/calculated-%02d' % index
os.mkdir(directory)
records = []
checks = []
EPS0 = 8.85418781762e-12
def real(value):
if isinstance(value, (list, tuple)):
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 label(x, y, material, mesh, group=1):
ei_addblocklabel(x, y)
ei_selectlabel(x, y)
ei_setblockprop(material, 0, mesh, group)
ei_clearselected()
def circle(x, radius, conductor, angle):
ei_addnode(x - radius, 0)
ei_addnode(x + radius, 0)
ei_addarc(x - radius, 0, x + radius, 0, 180, angle)
ei_addarc(x + radius, 0, x - radius, 0, 180, angle)
ei_selectarcsegment(x, radius)
ei_selectarcsegment(x, -radius)
ei_setarcsegmentprop(angle, '<None>', 0, 0, conductor)
ei_clearselected()
def solve(model):
ei_saveas(model)
ei_close()
opendocument(model)
ei_analyze(1)
ei_loadsolution()
eo_smooth('off')
def electric_result(mesh, model, input_name, output_name, exact_C):
voltage_in, charge_in = eo_getconductorproperties(input_name)
voltage_out, charge_out = eo_getconductorproperties(output_name)
voltage = real(voltage_in) - real(voltage_out)
charge = real(charge_in)
eo_groupselectblock(1)
energy = real(eo_blockintegral(0))
eo_clearblock()
capacitance = charge / voltage
energy_C = 2 * energy / voltage ** 2
row = {'mesh_mm': mesh, 'model': os.path.basename(model),
'nodes': eo_numnodes(), 'elements': eo_numelements(),
'voltage_V': voltage, 'charge_C': charge, 'energy_J': energy,
'capacitance_F': capacitance, 'energy_capacitance_F': energy_C,
'analytic_capacitance_F': exact_C,
'analytic_C_relative_error': abs(capacitance / exact_C - 1),
'energy_charge_relative_error': abs(energy_C / capacitance - 1)}
records.append(row)
check('Энергия и заряд: ' + os.path.basename(model),
row['energy_charge_relative_error'], 1e-5)
return row
def circle_xy(cx, cy, radius, conductor, angle):
ei_addnode(cx - radius, cy)
ei_addnode(cx + radius, cy)
ei_addarc(cx - radius, cy, cx + radius, cy, 180, angle)
ei_addarc(cx + radius, cy, cx - radius, cy, 180, angle)
ei_selectarcsegment(cx, cy + radius)
ei_selectarcsegment(cx, cy - radius)
ei_setarcsegmentprop(angle, '<None>', 0, 0, conductor)
ei_clearselected()
def polygon(points, conductor='<None>', mesh=0):
for x, y in points:
ei_addnode(x, y)
for k, (x, y) in enumerate(points):
x2, y2 = points[(k + 1) % len(points)]
ei_addsegment(x, y, x2, y2)
if conductor != '<None>':
ei_selectsegment((x + x2) / 2, (y + y2) / 2)
ei_setsegmentprop('<None>', mesh, 0, 0, 0, conductor)
ei_clearselected()
def terminal(x, y, name, mesh):
ei_selectsegment(x, y)
ei_setsegmentprop('<None>', mesh, 0, 0, 0, name)
ei_clearselected()
def summary(mesh, model, source, ground, exact_C=None):
v1, q1 = eo_getconductorproperties(source)
v0, q0 = eo_getconductorproperties(ground)
v1, v0, q1, q0 = real(v1), real(v0), real(q1), real(q0)
voltage = v1 - v0
eo_groupselectblock(1)
energy = real(eo_blockintegral(0))
eo_clearblock()
capacitance = q1 / voltage
row = {'mesh_mm': mesh, 'model': os.path.basename(model),
'nodes': eo_numnodes(), 'elements': eo_numelements(),
'voltage_V': voltage, 'charge_C': q1, 'energy_J': energy,
'capacitance_F': capacitance,
'energy_capacitance_F': 2 * energy / voltage ** 2}
if exact_C is not None:
row['analytic_capacitance_F'] = exact_C
row['analytic_C_relative_error'] = abs(capacitance / exact_C - 1)
records.append(row)
check('Энергия и терминальный заряд: ' + os.path.basename(model),
abs(2 * energy / voltage ** 2 / capacitance - 1), 1e-5)
return row
def field(x, y):
values = eo_getpointvalues(x, y)
return math.sqrt(real(values[3]) ** 2 + real(values[4]) ** 2)
def rectangle_field(mesh, filename, epsx=2, epsy=2, voltage=100, width=10, height=10, depth=100):
newdocument(1)
ei_probdef('millimeters', 'planar', 1e-10, depth, 30)
ei_addmaterial('Диэлектрик учебного образца', epsx, epsy, 0)
ei_addconductorprop('Питающий электрод', voltage, 0, 1)
ei_addconductorprop('Заземлённый электрод', 0, 0, 1)
polygon(((0, 0), (width, 0), (width, height), (0, height)))
terminal(0, height / 2, 'Питающий электрод', mesh)
terminal(width, height / 2, 'Заземлённый электрод', mesh)
label(width / 2, height / 2, 'Диэлектрик учебного образца', mesh)
model = directory + '/' + filename + '.fee'
solve(model)
return model
def rounded_square(radius, angle, mesh):
b = 3
points = ((b - radius, b), (-b + radius, b), (-b, b - radius),
(-b, -b + radius), (-b + radius, -b), (b - radius, -b),
(b, -b + radius), (b, b - radius))
for x, y in points:
ei_addnode(x, y)
for k in range(8):
x, y = points[k]
x2, y2 = points[(k + 1) % 8]
if k % 2 == 0:
ei_addsegment(x, y, x2, y2)
terminal((x + x2) / 2, (y + y2) / 2, 'Скруглённый электрод', mesh)
else:
ei_addarc(x, y, x2, y2, 90, angle)
p = b - radius + radius / math.sqrt(2)
for x, y in ((p, p), (-p, p), (-p, -p), (p, -p)):
ei_selectarcsegment(x, y)
ei_setarcsegmentprop(angle, '<None>', 0, 0, 'Скруглённый электрод')
ei_clearselected()
for radius in (0.2, 0.5, 1.0):
for level, mesh in enumerate((0.15, 0.075, 0.0375)):
newdocument(1)
ei_probdef('millimeters', 'planar', 1e-10, 10, 30)
ei_addmaterial('Воздух вокруг электрода', 1, 1, 0)
ei_addconductorprop('Скруглённый электрод', 100, 0, 1)
ei_addconductorprop('Заземлённый круговой экран', 0, 0, 1)
angle = 4 / (2 ** level)
rounded_square(radius, angle, mesh)
circle(0, 12, 'Заземлённый круговой экран', angle)
label(0, 0, '<No Mesh>', mesh, 0)
label(6, 0, 'Воздух вокруг электрода', mesh)
model = directory + '/rounding-%02d-%02d.fee' % (int(radius * 10), level + 1)
solve(model)
row = summary(mesh, model, 'Скруглённый электрод', 'Заземлённый круговой экран')
sample = 3 - radius + (radius + 0.2) / math.sqrt(2)
row['rounding_radius_mm'] = radius
# Для локальной производной используем восстановленное узловое поле;
# заряд и энергия выше получены независимо от этого сглаживания.
eo_smooth('on')
row['E_corner_sample_V_m'] = field(sample, sample)
eo_close()
ei_close()
check('Сходимость ёмкости при радиусе ' + str(radius), abs(records[-1]['capacitance_F'] / records[-2]['capacitance_F'] - 1), 0.005)
check('Сходимость поля в 0,2 мм от скругления ' + str(radius), abs(records[-1]['E_corner_sample_V_m'] / records[-2]['E_corner_sample_V_m'] - 1), 0.05)
check('Скругление снижает поле в заданной контрольной точке',
max(0, records[8]['E_corner_sample_V_m'] / records[2]['E_corner_sample_V_m'] - 1), 0)
columns = {
'mesh_mm': 'Размер сетки, мм', 'model': 'Файл модели',
'nodes': 'Узлов', 'elements': 'Элементов',
'voltage_V': 'Разность потенциалов, В', 'charge_C': 'Заряд, Кл',
'energy_J': 'Энергия, Дж', 'capacitance_F': 'Ёмкость по заряду, Ф',
'energy_capacitance_F': 'Ёмкость по энергии, Ф',
'analytic_capacitance_F': 'Аналитическая ёмкость, Ф',
'analytic_C_relative_error': 'Относительная ошибка ёмкости',
'energy_charge_relative_error': 'Невязка энергии и заряда',
'E_7p5mm_V_m': 'Поле при r=7,5 мм, В/м',
'analytic_E_7p5mm_V_m': 'Аналитическое поле при r=7,5 мм, В/м',
'E_150mm_V_m': 'Поле при r=150 мм, В/м',
'analytic_E_150mm_V_m': 'Аналитическое поле при r=150 мм, В/м',
'outer_radius_mm': 'Радиус внешней границы, мм',
'insulation': 'Изоляция', 'analytic_Emax_kV_mm': 'Аналитический максимум поля, кВ/мм',
'Emax_from_charge_kV_mm': 'Максимум поля по заряду, кВ/мм',
'E_10mm_kV_mm': 'Поле при r=10 мм, кВ/мм',
'E_25mm_kV_mm': 'Поле при r=25 мм, кВ/мм',
'conductivity_S_m': 'Эквивалентная проводимость, См/м',
'I_real_A': 'Активная компонента амплитуды тока, А',
'I_imag_A': 'Квадратурная компонента амплитуды тока, А',
'analytic_I_real_A': 'Аналитическая активная компонента, А',
'analytic_I_imag_A': 'Аналитическая квадратурная компонента, А',
'losses_W': 'Диэлектрические потери, Вт',
'analytic_losses_W': 'Аналитические потери, Вт',
'terminal_power_W': 'Средняя мощность электрода, Вт',
'apparent_power_VA': 'Полная мощность, ВА',
'U_RMS_V': 'Действующее напряжение, В', 'U_amplitude_V': 'Амплитуда напряжения, В'
}
columns.update({'orientation': 'Ориентация главных осей', 'E_center_V_m': 'Поле в центре, В/м', 'E_first_V_m': 'Поле первого слоя, В/м', 'E_second_V_m': 'Поле второго слоя, В/м', 'interface_V': 'Потенциал интерфейса, В', 'floating_voltage_V': 'Потенциал изолированного электрода, В', 'floating_charge_C': 'Заряд изолированного электрода, Кл', 'overlap_mm': 'Перекрытие электродов, мм', 'rounding_radius_mm': 'Радиус скругления, мм', 'E_corner_sample_V_m': 'Поле в 0,2 мм от скругления, В/м', 'screen': 'Исполнение', 'E_inner_sample_V_m': 'Поле в контрольной точке, В/м', 'excited_phase': 'Возбуждённая фаза', 'C_Aj_F': 'Коэффициент строки A, Ф', 'C_Bj_F': 'Коэффициент строки B, Ф', 'C_Cj_F': 'Коэффициент строки C, Ф'})
result = {'runtime': 'FEMM 5.0; встроенный MicroPython', 'records': records,
'checks': checks, 'columns': columns,
'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: 9. Выполнено проверок: 16. Полная точность чисел и условия сравнения доступны в таблицах результатов JSON.
| Размер сетки, мм | Разность потенциалов, В | Заряд, Кл | Элементов | Радиус скругления, мм | Файл модели | Ёмкость по энергии, Ф | Ёмкость по заряду, Ф | Поле в 0,2 мм от скругления, В/м | Энергия, Дж | Узлов |
|---|---|---|---|---|---|---|---|---|---|---|
| 0,15 | 100 | 45,47 × 10⁻¹² | 43771 | 0,2 | rounding-02-01.fee | 454,7 × 10⁻¹⁵ | 454,7 × 10⁻¹⁵ | 32600 | 2,274 × 10⁻⁹ | 22298 |
| 0,075 | 100 | 45,45 × 10⁻¹² | 173472 | 0,2 | rounding-02-02.fee | 454,5 × 10⁻¹⁵ | 454,5 × 10⁻¹⁵ | 34020 | 2,273 × 10⁻⁹ | 87541 |
| 0,0375 | 100 | 45,44 × 10⁻¹² | 691061 | 0,2 | rounding-02-03.fee | 454,4 × 10⁻¹⁵ | 454,4 × 10⁻¹⁵ | 33250 | 2,272 × 10⁻⁹ | 347270 |
| 0,15 | 100 | 45,13 × 10⁻¹² | 43759 | 0,5 | rounding-05-01.fee | 451,3 × 10⁻¹⁵ | 451,3 × 10⁻¹⁵ | 30130 | 2,257 × 10⁻⁹ | 22284 |
| 0,075 | 100 | 45,11 × 10⁻¹² | 173595 | 0,5 | rounding-05-02.fee | 451,1 × 10⁻¹⁵ | 451,1 × 10⁻¹⁵ | 31420 | 2,256 × 10⁻⁹ | 87621 |
| 0,0375 | 100 | 45,11 × 10⁻¹² | 691455 | 0,5 | rounding-05-03.fee | 451,1 × 10⁻¹⁵ | 451,1 × 10⁻¹⁵ | 31460 | 2,255 × 10⁻⁹ | 347772 |
| 0,15 | 100 | 44,4 × 10⁻¹² | 43710 | 1 | rounding-10-01.fee | 444 × 10⁻¹⁵ | 444 × 10⁻¹⁵ | 27980 | 2,22 × 10⁻⁹ | 22232 |
| 0,075 | 100 | 44,38 × 10⁻¹² | 173376 | 1 | rounding-10-02.fee | 443,8 × 10⁻¹⁵ | 443,8 × 10⁻¹⁵ | 28490 | 2,219 × 10⁻⁹ | 87583 |
| 0,0375 | 100 | 44,38 × 10⁻¹² | 691260 | 1 | rounding-10-03.fee | 443,8 × 10⁻¹⁵ | 443,8 × 10⁻¹⁵ | 28700 | 2,219 × 10⁻⁹ | 347147 |
| Критерий | Получено | Допуск или ожидаемое значение | Итог |
|---|---|---|---|
| Энергия и терминальный заряд: rounding-02-01.fee | 749 × 10⁻¹² | 1e-05 | Выполнен |
| Энергия и терминальный заряд: rounding-02-02.fee | 1,313 × 10⁻⁹ | 1e-05 | Выполнен |
| Энергия и терминальный заряд: rounding-02-03.fee | 719,4 × 10⁻¹² | 1e-05 | Выполнен |
| Сходимость ёмкости при радиусе 0.2 | 135 × 10⁻⁶ | 0,005 | Выполнен |
| Сходимость поля в 0,2 мм от скругления 0.2 | 0,0228 | 0,05 | Выполнен |
| Энергия и терминальный заряд: rounding-05-01.fee | 439,5 × 10⁻¹² | 1e-05 | Выполнен |
| Энергия и терминальный заряд: rounding-05-02.fee | 767,8 × 10⁻¹² | 1e-05 | Выполнен |
| Энергия и терминальный заряд: rounding-05-03.fee | 860,4 × 10⁻¹² | 1e-05 | Выполнен |
| Сходимость ёмкости при радиусе 0.5 | 118,1 × 10⁻⁶ | 0,005 | Выполнен |
| Сходимость поля в 0,2 мм от скругления 0.5 | 0,001413 | 0,05 | Выполнен |
| Энергия и терминальный заряд: rounding-10-01.fee | 734,2 × 10⁻¹² | 1e-05 | Выполнен |
| Энергия и терминальный заряд: rounding-10-02.fee | 1,243 × 10⁻⁹ | 1e-05 | Выполнен |
| Энергия и терминальный заряд: rounding-10-03.fee | 975,5 × 10⁻¹² | 1e-05 | Выполнен |
| Сходимость ёмкости при радиусе 1.0 | 97,96 × 10⁻⁶ | 0,005 | Выполнен |
| Сходимость поля в 0,2 мм от скругления 1.0 | 0,00756 | 0,05 | Выполнен |
| Скругление снижает поле в заданной контрольной точке | 0 | 0 | Выполнен |
Допуски относятся к указанной учебной задаче и способу сравнения. Число показанных цифр не означает такой же физической точности.
Модели, решения и программа
Для нового расчёта сохраните программу, модели и необходимые данные в одну рабочую папку, сохраняя структуру подпапок.
- Файл результатов: README.md1193 байт
- Программа встроенного Python: reproduce.py12840 байт
- Электростатическая модель: rounding-02-01.fee1430 байт
- Электростатическое решение: rounding-02-01.res2221757 байт
- Электростатическая модель: rounding-02-02.fee1435 байт
- Электростатическое решение: rounding-02-02.res8969230 байт
- Электростатическая модель: rounding-02-03.fee1435 байт
- Электростатическое решение: rounding-02-03.res37358171 байт
- Электростатическая модель: rounding-05-01.fee1310 байт
- Электростатическое решение: rounding-05-01.res2216033 байт
- Электростатическая модель: rounding-05-02.fee1315 байт
- Электростатическое решение: rounding-05-02.res8968481 байт
- Электростатическая модель: rounding-05-03.fee1315 байт
- Электростатическое решение: rounding-05-03.res37373442 байт
- Электростатическая модель: rounding-10-01.fee1294 байт
- Электростатическое решение: rounding-10-01.res2214742 байт
- Электростатическая модель: rounding-10-02.fee1299 байт
- Электростатическое решение: rounding-10-02.res8962421 байт
- Электростатическая модель: rounding-10-03.fee1299 байт
- Электростатическое решение: rounding-10-03.res37353998 байт
Границы применимости
- Контролируется поле в одной заданной точке, а не поверхностный максимум.
- Модель линейна; корона, пробой и конечная проводимость электрода не рассматриваются.