1、辅助函数
辅助函数是用于支持主函数计算的工具函数。它通常用于处理特定的计算任务,如生成初始条件。目的在于生成初始条件时,特别是在求解 PDE时,通常通过傅里叶级数表示来构造初始状态。
如 Burgers 方程,初始条件,t=0时状态,u(x,0) = f(x),其中f(x)形式固定为类似傅里叶级数形式,那么有,其中
为随机系数(random coefficients)常数,故相同X位置空间中,
不同的
对应不同初始状态。
1.1 傅里叶级数(Fourier series)
形式:
这是一个周期性函数,使用正弦函数的线性组合表示,其中是函数在区间上的平均值,系数
通常是根据特定问题的初始条件或边界条件来确定的,可以是常数或函数,傅里叶系数有
。这种表示方式常用于描述平滑、可微的物理现象,比如流体的速度分布。
Python Jax 实现类傅里叶级数辅助函数:
def generate_initial_condition_funtion(N, key):"""Generate an initial condition that is 2π-periodic and has zero mean in the interval [-π, π].Args:N (int): Number of sine terms to include in the Fourier series.key (jax.random.PRNGKey): A random number generator key.Returns:callable: A function representing the initial condition."""# Generate random coefficients for the sine termscoefficients = A * random.normal(key, (N,))def initial_condition_funtion(x):sine_terms = np.zeros_like(x)for n in range(N):sine_terms += coefficients[n] * np.sin((n + 1) * x)# Set small values to zerothreshold = 1e-14sine_terms = np.where(np.abs(sine_terms) < threshold, 0, sine_terms)return sine_termsreturn initial_condition_funtion
2、随机函数
随机函数是定义在某个概率空间上的函数,其值受到随机性的影响。高斯随机场(GRF)就是一种随机函数。目的于:模拟具有不确定性的现象,捕捉数据中的随机性;用于统计建模、机器学习和其他需要考虑不确定性的领域。
如 Burgers 方程,初始条件,t=0时状态,u(x,0) = f(x),其中f(x)由高斯核随机场GRF生成映射关系,符合一个随机函数。,其中
是均值函数,
是协方差函数。GRF 是随机的,意味着对于任意两个点x和 x,f(x) 和 f(x′) 之间的关系是随机的,且符合高斯分布(normal distribution,正态分布)。GRF 可用于建模空间或时间上具有不确定性的现象,如生成随机状态函数、初始条件。
2.1 高斯核(Gaussian kernel)
形式:
其中是协方差函数,也是高斯核函数,
为振幅,
为长度尺度(或带宽)。
高斯核是一个正定核,意味着它可以用于构建有效的内积空间。它具有平滑性和局部性,距离越近的点相似度越高。高斯核(Gaussian kernel)与正态分布(normal distribution)密切相关,但它们并不完全相同。高斯核是用于计算数据点之间相似度的函数,通常用于机器学习和统计建模。正态分布是指随机变量的概率分布,具有钟形曲线的特征。
2.2 径向基函数核(Radial Basis Function,RBF)
RBF核,通常被定义为高斯核的一种特例,其一般形式为
其中 γ是一个参数,通常与高斯核中的长度尺度成反比。
高斯核和RBF核在本质上是相同的,都是用于计算数据点相似度的函数,两者在支持向量机(SVM)、核回归、聚类等机器学习算法中广泛使用,用于处理非线性问题。
MatLab实现GRF高斯随机场生成随机函数代码:
%Radom function from N(m, C) on [0 1] where
%C = sigma^2(-Delta + tau^2 I)^(-gamma)
%with periodic, zero dirichlet, and zero neumann boundary.
%Dirichlet only supports m = 0.
%N is the # of Fourier modes, usually, grid size / 2.
function u = GRF(N, m, gamma, tau, sigma, type)if type == "dirichlet"m = 0;
endif type == "periodic"my_const = 2*pi;
elsemy_const = pi;
endmy_eigs = sqrt(2)*(abs(sigma).*((my_const.*(1:N)').^2 + tau^2).^(-gamma/2));if type == "dirichlet"alpha = zeros(N,1);
elsexi_alpha = randn(N,1);alpha = my_eigs.*xi_alpha;
endif type == "neumann"beta = zeros(N,1);
elsexi_beta = randn(N,1);beta = my_eigs.*xi_beta;
enda = alpha/2;
b = -beta/2;c = [flipud(a) - flipud(b).*1i;m + 0*1i;a + b.*1i];if type == "periodic"uu = chebfun(c, [0 1], 'trig', 'coeffs');u = chebfun(@(t) uu(t - 0.5), [0 1], 'trig');
elseuu = chebfun(c, [-pi pi], 'trig', 'coeffs');u = chebfun(@(t) uu(pi*t), [0 1]);
end
Python Jax实现使用RBF核和cholesky分解实现随机函数,输出自变量与因变量映射关系:
# Define RBF kernel
def RBF(x1, x2, params):output_scale, lengthscales = paramsdiffs = np.expand_dims(x1 / lengthscales, 1) - \np.expand_dims(x2 / lengthscales, 0)r2 = np.sum(diffs**2, axis=2)return output_scale * np.exp(-0.5 * r2)# Sample GP prior at a fine grid
N = 512
gp_params = (1.0, length_scale)
jitter = 1e-10
X = np.linspace(0, 1, N)[:,None] #shape (512, 1)
K = RBF(X, X, gp_params) #shape (512, 512)
L = np.linalg.cholesky(K + jitter*np.eye(N)) #shape (512, 512)
gp_sample = np.dot(L, random.normal(key_train, (N,)))#使用RBF核和Cholesky分解来从高斯过程中采样, shape (512,)# Create a callable interpolation function
u_fn = lambda x, t: np.interp(t, X.flatten(), gp_sample)