Важным соображением для FiPy является то, что индексация сетки не основана на индексации сетки, поэтому при сопоставлении массива сетки со значениями ячеек не следует предполагать, что сетка упорядочена каким-либо конкретным образом. Это делает необходимым использование некоторой формы интерполяции. Давайте сначала построим поле скорости с индексацией сетки, где точки лежат на точках сетки (не центрах ячеек).
from fipy import Grid2D, CellVariable, FaceVariable
from fipy import ConvectionTerm, DiffusionTerm, TransientTerm
import numpy as np
from scipy import interpolate
dx = 0.5
nx = 7
dy = 0.5
ny = 7
xy = np.zeros((nx, ny, 2))
xy[:, :, 0] = np.mgrid[0:nx, 0:ny][0] * dx
xy[:, :, 1] = np.mgrid[0:nx, 0:ny][1] * dy
u = xy[..., 0] + xy[..., 1]
v = xy[..., 0] * xy[..., 1]
Теперь у нас есть поле скорости (u, v)
, каждое из которых имеет форму nx, ny
и соответствующий емукоординаты xy
, формы (nx, ny, 2)
. Допустим, мы хотим интерполировать это на сетку FiPy с тем же доменом, но с другой сеткой.
m = Grid2D(nx=3, ny=3, dx=1.0, dy=1.0)
Сетка не обязательно должна совпадать с точками сетки для поля скорости. Затем мы можем интерполировать эту сетку с помощью
xy_interp = np.array(m.faceCenters).swapaxes(0, 1)
u_interp = interpolate.griddata(xy.reshape(-1, 2), u.flatten(), xy_interp, method='cubic')
v_interp = interpolate.griddata(xy.reshape(-1, 2), v.flatten(), xy_interp, method='cubic')
, где xy_interp
- это грани центра сетки. Обратите внимание, что использование griddata
требует, чтобы xy_interp
находилось внутри xy
, иначе это дает значения nan. Получив интерполированные значения, мы можем установить поле скорости FiPy.
velocity = FaceVariable(mesh=m, rank=1)
velocity[0, :] = u_interp
velocity[1, :] = v_interp
Обратите внимание, что коэффициент для ConvectionTerm
может быть FaceVariable
или CellVariable
. Как только у нас будет скорость, мы готовы установить и решить уравнение.
var = CellVariable(mesh=m)
eqn = (TransientTerm() + ConvectionTerm(velocity) == DiffusionTerm(1.0))
eqn.solve(var, dt=1.0)
Для меня это работает без ошибок.
Ссылка на полный сценарий для этой задачи