2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2
 
 Re: Решение краевой задачи
Сообщение28.10.2021, 12:03 


17/03/20
183
kotenok gav


Вот в том и проблема, что я не понимаю, почему такая ошибка... Я решил распечатать в цикле все значения u[i], u_n[i], дабы убедиться, что это массивы, и действительно они таковыми являются, а как правило такая ошибка возникает, если такие объекты не могут иметь индекс, не индексируемые... Потому я не понимаю, в чем проблема...

Да, q- число, все верно, но мне же надо вычислять значения для каждого узла сетки...

 Профиль  
                  
 
 Re: Решение краевой задачи
Сообщение28.10.2021, 12:20 


21/05/16
4292
Аделаида
Так вы пишете q[i] и q[i + 1]. А q не массив.

 Профиль  
                  
 
 Re: Решение краевой задачи
Сообщение28.10.2021, 20:33 


17/03/20
183
kotenok gav

Придется все переписать, скорее всего, попробую тогда это сделать...

 Профиль  
                  
 
 Re: Решение краевой задачи
Сообщение29.10.2021, 21:21 


17/03/20
183
kotenok gav
В общем попытался переписать код иначе, единственный вопрос у меня возникает в том,что я не уверен, что решение получено точное, и еще как бы вывести в нормальном формате столбцы ndarray (я имею ввиду виде таблицы например) и почему значение для последнего узла сетки равно нулю, я тоже понять не могу? К сожалению не получается из отдельных кадров создать анимацию, к тому же не на всех кадрах прорисовывается сетка... Не знаю как это исправить.... Может есть какие предложения?

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

К сожалению, касаемо скорости работы программы не могу ничего сказать хорошего, возможно стоит использовать векторизацию, может быть, я правда не знаю, что можно сделать, может есть другой способ создать видеоанимацию?

код: [ скачать ] [ спрятать ]
Используется синтаксис Python
  1.  
  2. # Author: Alm99-collab
  3. # Date: 25/10/2021 2:00
  4. # Description: MSUT STANKIN Μyagkov Alexandr IDM - 21 - 03
  5.  
  6.  
  7. """
  8. Программа для численного решения волнового уравнения в одномерном случае,
  9. при разлинчых начальных и граничных условий, с помощью явной разностной
  10. схемы типа "крест".
  11.  
  12. Общий вид волнового уравнения:
  13. u_tt = a**2*u_xx + f(x,t) (0,L) где u=0 на диапазоне x=0,L, for t in (0,T].
  14. Начальные условия в общем случае: u=I(x), u_t=V(x).
  15. В случае неоднородного уравнения задается функция f(x,t).
  16.  
  17. Синтакис основной функции решателя:
  18. u, x, t = solver(I, V, f, a, L, dt, C, T, user_func) где:
  19. I = I(x) - функция.
  20. V = V(x) - функция.
  21. f = f(x,t) - функция.
  22. U_0, U_L, - условия на границе.
  23. C - число Куранта (=a*dt/dx), зависящее от шага dx. Является криетрием
  24. стабильности численных расчето, если соблюдено условие (<=1)
  25. dt - шаг по времени.
  26. dx - шаг по координате.
  27. T - конечное время симуляции волнового процесса.
  28. user_func - функция (u, x, t, n) для вызова пользовательских сценариев,
  29. таких как анимация или вывод графика, запси данных в текстовый файл,
  30. расчет ошибки (в случае если известно точное решение) и.т.д.
  31. """
  32.  
  33. import numpy as np
  34. import math
  35. import matplotlib.pyplot as plt
  36. import os
  37. import time
  38. import glob
  39.  
  40.  
  41. # функция решатель для данного дифференциального уравнения
  42. def solver(I, V, f, a, U_0, U_L, L, dt, C, T,
  43.            user_func = None):
  44.     """
  45.    Функция решения волнового уравнения u_tt = a**2*u_xx + f(x,t) (0,L),
  46.    где u=0 на диапазоне x=0,L, for t in (0,T].
  47.    Начальные условия в общем случае: u=I(x), u_t=V(x).
  48.    В случае неоднородного уравнения задается функция f(x,t).
  49.    ------------------------------------------------------------------------
  50.    :param I:
  51.    :param V:
  52.    :param f:
  53.    :param a:
  54.    :param L:
  55.    :param C:
  56.    :param T:
  57.    :param U_0:
  58.    :param U_L:
  59.    :param dt:
  60.    :param user_func:
  61.    :return:
  62.    """
  63.  
  64.     nt = int(round(T / dt))
  65.     t = np.linspace(0, nt * dt, nt + 1)  # Узлы сетки по времени
  66.     dx = dt * a / float(C)
  67.     nx = int(round(L / dx))
  68.     x = np.linspace(0, L, nx + 1)  # Узлы сетки по координате
  69.     C2 = C ** 2
  70.     dt2 = dt * dt
  71.  
  72.     # Проверка того, что  массивы являются элементами t,x
  73.     dx = x[1] - x[0]
  74.     dt = t[1] - t[0]
  75.  
  76.     # Выбор и инициализация дополнительных параметров f, I, V, U_0, U_L если равны нулю
  77.     # или не передаются
  78.     if f is None or f == 0:
  79.         f = lambda x, t: 0
  80.     if I is None or I == 0:
  81.         I = lambda x: 0
  82.     if V is None or V == 0:
  83.         V = lambda x: 0
  84.     if U_0 is not None:
  85.         if isinstance(U_0, (float, int)) and U_0 == 0:
  86.             U_0 = lambda t: 0
  87.         # иначе: U_0(t) является функцией
  88.     if U_L is not None:
  89.         if isinstance(U_L, (float, int)) and U_L == 0:
  90.             U_L = lambda t: 0
  91.         # иначе: U_L(t) является функцией
  92.  
  93.     # ---  Выделяем память под значения решений  ---
  94.     u = np.zeros(nx + 1)  # Массив решений в узлах сетки на  временном шаге u(i,n+1)
  95.     u_n = np.zeros(nx + 1)  # Массив решений в узлах сетки на  временном шаге u(i,n)
  96.     u_nm1 = np.zeros(nx + 1)  # Массив решений в узлах сетки на  временном шаге u(i,n-1)
  97.  
  98.     # --- Проверка индексов для соблюдения размерностей массивов ---
  99.     Ix = range(0, nx + 1)
  100.     It = range(0, nt + 1)
  101.  
  102.     # --- Запись начальных условий ---
  103.     for i in Ix:
  104.         u_n[i] = I(x[i])
  105.  
  106.     if user_func is not None:
  107.         user_func(u_n, x, t, 0)
  108.  
  109.     # --- Разностная формулма явной схемы "типа крест" на первом шаге ---
  110.     for i in Ix[1:-1]:
  111.         u[i] = u_n[i] + dt * V(x[i]) + 0.5 * C2 * (u_n[i - 1] - 2 * u_n[i] + u_n[i + 1]) + 0.5 * dt2 * f(x[i], t[0])
  112.  
  113.     i = Ix[0]
  114.     if U_0 is None:
  115.         # Запись граничных условий (x=0: i-1 -> i+1  u[i-1]=u[i+1]
  116.         # где du/dn = 0, on x=L: i+1 -> i-1  u[i+1]=u[i-1])
  117.         ip1 = i + 1
  118.         im1 = ip1  # i-1 -> i+1
  119.         u[i] = u_n[i] + dt * V(x[i]) + 0.5 * C2 * (u_n[im1] - 2 * u_n[i] + u_n[ip1]) + 0.5 * dt2 * f(x[i], t[0])
  120.  
  121.     else:
  122.         u[0] = U_0(dt)
  123.  
  124.     i = Ix[-1]
  125.     if U_L is None:
  126.         im1 = i - 1
  127.         ip1 = im1  # i+1 -> i-1
  128.         u[i] = u_n[i] + dt * V(x[i]) + 0.5 * C2 * (u_n[im1] - 2 * u_n[i] + u_n[ip1]) + 0.5 * dt2 * f(x[i], t[0])
  129.     else:
  130.         u[i] = U_L(dt)
  131.  
  132.     if user_func is not None:
  133.         user_func(u_n, x, t, 1)
  134.  
  135.     # Обновление данных и подготовка к новому шагу
  136.     u_nm1, u_n, u = u_n, u, u_nm1
  137.  
  138.     # --- Симуляция (цикл прохода по времени) ---
  139.     for n in It[1:-1]:
  140.         # Обновление значений во внутренних узлах сетки
  141.         for i in Ix[1:-1]:
  142.             u[i] = - u_nm1[i] + 2 * u_n[i] + C2 * (u_n[i - 1] - 2 * u_n[i] + u_n[i + 1]) + dt2 * f(x[i], t[n])
  143.  
  144.         #  --- Запись граничных условий ---
  145.         i = Ix[0]
  146.         if U_0 is None:
  147.             # Установка значений граничных условий
  148.             # x=0: i-1 -> i+1  u[i-1]=u[i+1] где du/dn=0
  149.             # x=L: i+1 -> i-1  u[i+1]=u[i-1] где du/dn=0
  150.             ip1 = i + 1
  151.             im1 = ip1
  152.             u[i] = - u_nm1[i] + 2 * u_n[i] + C2 * (u_n[im1] - 2 * u_n[i] + u_n[ip1]) + dt2 * f(x[i], t[n])
  153.         else:
  154.             u[0] = U_0(t[n + 1])
  155.  
  156.         i = Ix[-1]
  157.         if U_L is None:
  158.             im1 = i - 1
  159.             ip1 = im1
  160.             u[i] = - u_nm1[i] + 2 * u_n[i] + C2 * (u_n[im1] - 2 * u_n[i] + u_n[ip1]) + dt2 * f(x[i], t[n])
  161.         else:
  162.             u[i] = U_L(t[n + 1])
  163.  
  164.         if user_func is not None:
  165.             if user_func(u, x, t, n + 1):
  166.                 break
  167.  
  168.         # Обновление данных и подготовка к новому шагу
  169.         u_nm1, u_n, u = u_n, u, u_nm1
  170.  
  171.     # Присвоение значений требуемому узлу после прохода по сетке
  172.     u = u_n
  173.  
  174.     return u, x, t
  175.  
  176.  
  177. # функция симуляции и анимации, сохранения данных в файл
  178. def simulate(I, V, f, a, U_0, U_L, L, dt, C, T, umin, umax, animate = True):
  179.  
  180.     """
  181.    Запуск решателя и анимации,сохранения данных в файл
  182.    ----------------------------------------------------------------------------
  183.    :param I:
  184.    :param V:
  185.    :param f:
  186.    :param a:
  187.    :param L:
  188.    :param dt:
  189.    :param C:
  190.    :param T:
  191.    :param umin:
  192.    :param umax:
  193.    :param U_0:
  194.    :param U_L:
  195.    :param animate:
  196.    :param mode:      # выбор режима работы (анимация и визуализация или запись данных в файл)
  197.    :return:
  198.    """
  199.  
  200.     if callable(U_0):
  201.         bc_left = 'u(0,t)=U_0(t)'
  202.     elif U_0 is None:
  203.         bc_left = 'du(0,t)/dx=0'
  204.     else:
  205.         bc_left = 'u(0,t)=0'
  206.     if callable(U_L):
  207.         bc_right = 'u(L,t)=U_L(t)'
  208.     elif U_L is None:
  209.         bc_right = 'du(L,t)/dx=0'
  210.     else:
  211.         bc_right = 'u(L,t)=0'
  212.  
  213.     class PlotMatplotlib:
  214.         def __call__(self, u, x, t, n):
  215.  
  216.             """ user_func для визуализации """
  217.  
  218.             if n == 0:
  219.                 plt.ion()
  220.                 self.lines = plt.plot(x, u, 'r-')
  221.                 plt.xlabel('x')
  222.                 plt.ylabel('u')
  223.                 plt.axis([0, L, umin, umax])
  224.                 plt.legend(['t=%f' % t[n]], loc = 'lower left')
  225.             else:
  226.                 self.lines[0].set_ydata(u)
  227.                 plt.legend(['t=%f' % t[n]], loc = 'lower left')
  228.                 plt.draw()
  229.                 plt.grid()
  230.             time.sleep(1) if t[n] == 0 else time.sleep(0.5)
  231.             plt.savefig('tmp_%04d.png' % n)  # для создания анимации из кадров
  232.  
  233.     plot_u = PlotMatplotlib()
  234.  
  235.     # Очистка фреймов для создания анимированного изображения
  236.     for filename in glob.glob('frame_*.png'):
  237.         os.remove(filename)
  238.  
  239.     fps = 4  # frames per second
  240.     codec2ext = dict(flv = 'flv', libx264 = 'mp4', libvpx = 'webm',
  241.                      libtheora = 'ogg')  # video formats
  242.     filespec = 'tmp_%04d.png'
  243.     movie_program = 'ffmpeg'  # or 'avconv'
  244.     for codec in codec2ext:
  245.         ext = codec2ext[codec]
  246.         cmd = '%(movie_program)s -r %(fps)d -i %(filespec)s ' \
  247.               '-vcodec %(codec)s movie.%(ext)s' % vars()
  248.         os.system(cmd)
  249.  
  250.     user_func = plot_u if animate else None
  251.     u, x, t = solver(I, V, f, a, U_0, U_L, L, dt, C, T, user_func)
  252.  
  253.     return u, x, t
  254.  
  255.  
  256. # функция постановки задачи
  257. def problem():
  258.     I = lambda x: 0.2 * (1 - x) * math.sin(math.pi * x)
  259.     V = lambda x: 0
  260.     f = lambda x, t: 0
  261.     U_0 = lambda t: 0
  262.     U_L = 0
  263.     L = 1
  264.     a = 1
  265.     C = 0.75
  266.     nx = 12
  267.     dt = C * (L / nx) / a
  268.     T = 1
  269.     umin = -0.25
  270.     umax = 0.25
  271.  
  272.     u, x, t = simulate(I, V, f, a, U_0, U_L, L, dt, C, T, umin, umax, animate=True)
  273.  
  274.     return u, x, t
  275.  
  276. if __name__ == '__main__':
  277.     u, x, t = problem()
  278.     print(u,x,t)
  279.  

 Профиль  
                  
 
 Re: Решение краевой задачи
Сообщение30.10.2021, 08:31 


21/05/16
4292
Аделаида
Alm99 в сообщении #1536941 писал(а):
я не уверен, что решение получено точное

Здесь ничем помочь не могу, извините. Я вообще не понимаю, что делает код.
Alm99 в сообщении #1536941 писал(а):
как бы вывести в нормальном формате столбцы ndarray (я имею ввиду виде таблицы например)

Я задал этот вопрос Гуглу, и - о чудо! - получил ответ (и я честно не понимаю, что удерживало вас от этого). В общем, существует модуль tabulate, с помощью которого можно вывести несколько массивов в виде таблицы. За деталями конвертации ndarray в массив массивов и вызова tabulate - к Гуглу.
Alm99 в сообщении #1536941 писал(а):
почему значение для последнего узла сетки равно нулю, я тоже понять не могу?

Насколько я вижу, переменные x и t задаются у вас один раз и потом никак не меняются. А если вы о u - то у вас же граничные условия задают его нулём, разве нет?
Alm99 в сообщении #1536941 писал(а):
не получается из отдельных кадров создать анимацию

Гугл в помощь.

Кстати, а зачем у вас в коде есть неиспользуемые переменные bc_left и bc_right и нет параметра mode в функции simulate, который должен быть согласно вашим комментариям? И зачем вы создаёте класс внутри функции?

 Профиль  
                  
 
 Re: Решение краевой задачи
Сообщение30.10.2021, 09:34 


17/03/20
183
kotenok gav

Цитата:
Здесь ничем помочь не могу, извините. Я вообще не понимаю, что делает код.

Решение краевой задачи,с возможностью задания различных начальный и краевых условий.

Цитата:
Насколько я вижу, переменные x и t задаются у вас один раз и потом никак не меняются. А если вы о u - то у вас же граничные условия задают его нулём, разве нет?

Я прошу у Вас прощения, я разобрался в чем была проблема...

Цитата:
Кстати, а зачем у вас в коде есть неиспользуемые переменные bc_left и bc_right и нет параметра mode в функции simulate, который должен быть согласно вашим комментариям? И зачем вы создаёте класс внутри функции?

Параметр mode нужен, чтобы я мог выбиарть режим с выводом графика или записью расчетных данных в файл. Просто я пока тестировал новый вариант, не стал писать этот кусок кода, дабы решить возникшие на данный момент проблемы...

А, про tabulate - посмотрю, спасибо за наводку!

 Профиль  
                  
 
 Re: Решение краевой задачи
Сообщение31.10.2021, 15:50 


17/03/20
183
kotenok gav
Удалось решить задачу! Спасибо за помощь!

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 22 ]  На страницу Пред.  1, 2

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group