простое в использовании адаптивное уточнение сетки для характеристической функции - Python

У меня есть (прерывистая) функция f от R^n до {0, 1}, предоставленная пользователем. Например. что-то вроде этого "круглого неравенства":

def charfunc(x):
    # assume x is a numpy array
    return x[0]**2 + x[1]**2  < 1

Я хочу найти границу области (областей), где f == 1, путем выборки значений функции в регулярной сетке и уточнить эту сетку (итеративно) в областях, где значение изменяется. Я думаю, что это не должно быть такой экзотической проблемой, и я уверен, что она уже решена во вселенной Python. Однако я нашел только сложные пакеты PDE/FEM и NDTAMR. Первые кажутся слишком большими накладными расходами. NDTAMR выглядит многообещающе, но дает странные результаты (по крайней мере, с параметрами по умолчанию из примеров):

Исходный круг Круг после уточнения

Есть уточненные ячейки, которые не близки к границе, а есть клетки, которые близки, но не очищены. Код для этого примера находится в этом репозитории.

Вопрос: Как использовать NDTAMR или какой-либо другой пакет Python, чтобы получить сетку, которая уточняется везде рядом с границей, но больше нигде?


person cknoll    schedule 06.12.2019    source источник


Ответы (2)


Я, наконец, реализовал это самостоятельно. Для простоты код находится в каком-то другом пакете, который я уже поддерживаю, но его можно использовать независимо практически без усилий:

https://github.com/TUD-RST/symbtools/blob/master/symbtools/meshtools.py

Некоторые юнит-тесты могут служить заменой отсутствующей документации.

введите здесь описание изображения

person cknoll    schedule 20.12.2019

Это должно быть достаточно легко сделать самостоятельно.

  • Для всех углов ваших четырехугольников проверьте, находятся ли они внутри или снаружи круга.
  • Уточните те четырехугольники, у которых есть узлы как внутри, так и снаружи, и вычислите статус для новых точек.

Я мог бы добавить, что такой поиск границ нетипичен для численного анализа. Обычно ваш домен определяется непрерывной функцией, отрицательной внутри и положительной вне домена, т. е.

def f(x):
    return x[0] ** 2 + x[1] ** 2 - 1

вместе с градиентом

def grad(x):
    return 2 * x 

(Градиент также может быть рассчитан автоматически.) Имея эту информацию, начиная с любой точки, вы можете затем выполнять итерации по направлению к границе.

person Nico Schlömer    schedule 11.12.2019
comment
Эта общая формулировка действительно очень проста. Однако реализация деталей для n измерений и общей функции кажется нетривиальной. Спасибо за подсказку, что моя проблема не типична. Теперь в вопросе явно упоминается разрывный характер данной функции. Использование градиента не вариант. - person cknoll; 20.12.2019