只知道法线的场的精确点积

计算科学 有限体积 向量
2021-12-28 12:30:55

我正在尝试为有限体积网格上的电子能量方程 是电子电流密度,是电场。在以顶点为中心的网格上,我知道在每个单元格的中心(其中)并且我还有一个计算的函数每个细胞的每个面。jEjEϕE=ϕjn^

使用值,我可以轻松计算问题是这两个法向分量相乘会忽略切向分量。在面上取最大值会导致 10-20% 的误差,并且对它们进行体积平均是完全不正确的(有几个因素)。我正在使用的当前解决方案是我也碰巧知道的方向,尽管我并不完全相信它。从物理学来看,在大多数情况下,在方向上接近是一个公平的假设,所以我假设它们在同一方向上,并除以 byϕEn^EjE(En^)(jn^)cos2θ垂直的 30 度以内的面,但它让我很接近E

我还找到了一个可行的解决方案,但使用了大量的三角函数,这可能太慢,无法在不稳定 FV 求解的每次迭代中在每个单元格处完成。该解决方案的工作原理是:

给定vn^1vn^2n^1n^2

v = 2*rand(1,2) - 1;    % Original vector we want to reproduce

n_1 = 2*rand(1,2) - 1;  % unit normal vectors
n_1 = n_1/norm(n_1);
n_2 = 2*rand(1,2) - 1;
n_2 = n_2/norm(n_2);

vn_1 = v.'*n_1;         % dot products
vn_2 = v.'*n_2;

thetaN1 = atan2(n_1(2), n_1(1));      % Calculate angle of first normal to x-axis
phi = thetaN1 - atan2(n_2(2),n_2(1)); % Difference in angle between normals

theta1 = atan((vn_1*cos(phi) - vn_2)/(vn_1*sin(phi)));  %Use both dot products to back out angle between first normal and v
v_mag = vn_1/cos(theta1);  % Back out magnitude of v

v_out(1) = v_mag*cos(thetaN1 + theta1);  % Calculate components of v
v_out(2) = v_mag*sin(thetaN1 + theta1);

v以上精确再现几乎双精度。即使我为每个点积在原始 v 中引入了大约 1% 的少量噪声(表示域在空间中从一个面的中心到另一个面的中心发生变化),它大多数情况下仍然精确到小数点后几位。正如我所说,这样做的成本比我想要的要高。我需要在每个时间步进行几百万次上述计算。 v

我觉得我有点重新发明了轮子,想知道当只知道面的正常分量时,是否有更有效和更通用的方法来计算两个字段的点积。

1个回答

我本来希望几何离散化将沿着网格的边缘放置(更准确地说,将是通过与网格边缘对偶的面的通量),在这种情况下,由网格顶点处的标量值表示. 这样,总是“活”在相同的网格元素上并且是共线的,从而可以轻松地评估点积。在您的表单中,似乎最好的办法就是细化网格。EjjϕEJ

您的代码片段可以大幅优化。我在图形中的常见技巧是注意只是跨越角度的两个单位向量的叉积的大小,而是它们的点积。这使您可以完全避免计算三角函数,并将所有内容简化为向量代数。此外,您通常不需要对向量进行归一化,因为如果您最终采用比率,则幅度会抵消。sinθcosθ