Я написал вычислительное моделирование, которое принимает некоторые необязательные параметры (в качестве граничных условий). Как показано в коде ниже
def leapfrog(dx, dt, u_0, v_0, U, V, u_l=None, u_r=None, v_l=None, v_r=None,
n_max=None, **kwargs):
"""Every call returns a timestep of leapfrog iteration given:
dx: Spatial step
dt: Time step
u0: Initial condition of regular grid
v0: Initial condition of staggered grid
U: Operator to apply over the regular grid
V: Operator to apply over staggered grid
u_l: left boundary condition to regular grid
u_r: right boundary condition to regular grid
v_l: left boundary condition to staggered grid
v_r: right boundary conditiion to staggered grid
n_max: If nmax is given, stops after n_max iterations (> 2)
For every call returns another timestep
"""
# Initial condition
yield u_0, v_0
# First iteration
u = u_0 - (dt/dx) * (V @ v_0)
if u_l is not None:
u[:len(u_l)] = u_l
if u_r is not None:
u[-len(u_r):] = u_r
v = v_0 - (dt/dx) * (U @ u_0)
if v_l is not None:
v[:len(v_l)] = v_l
if v_r is not None:
v[-len(v_r):] = v_r
yield u, v
# All other iterations
for n in itertools.count(start=2, step=1):
u = u - (dt/dx) * (V @ v)
if u_l is not None:
u[:u_l.size] = u_l
if u_r is not None:
u[-u_r.size:] = u_r
v = v - (dt/dx) * (U @ u)
if v_l is not None:
v[:v_l.size] = v_l
if v_r is not None:
v[-v_r.size:] = v_r
if n_max is not None and n >= n_max:
break
yield u,v
Хотя код работает нормально, он наверняка вызывает ветвление ЦП, поскольку я проверяю, добавил ли я граничное условие в основную и вторичную сетку (u
и v
) слева и справа (_l
и _r
) Например, u_l
означает условие левой границы в основной сетке.
u_l
, u_r
, v_l
и v_r
являются массивами типа numpy, такими как np.array([0])
. Мне нужно добавить размерность, в противном случае (если масштабатор) у него нет len, а также это делает вещи более равномерными .
В других руках иногда я не хочу добавлять граничные условия, в этих случаях я использую оператор if
, чтобы поймать его.
У меня вопрос, есть ли способ избежать разветвления (и все если)?
Конечно, я мог бы создавать «специализированные» функции с и без граничных условий (в основной и вторичной сетках), но я ищу более общий подход.
Также приветствуются любые другие советы по улучшению кода.