有一个和接触分析非常类似的领域,那就是不同物理场、不同结果数据之间的映射插值,如果需要互相映射插值的两者是有网格数据的,那么插值的过程与接触计算基本上没啥差异,还更简单一些,但如果其中一套数据是基于节点的,而没有网格单元信息,则需要用到KNN (K近邻点, k nearest nodes)与径向基函数 (RBF, radial basis functions)进行映射插值。
很多做神经网络的朋友们可能都听过KNN,但这个的KNN更加的清晰明确,就是找离一个节点最近的k个对应的节点,做多物理场仿真(尤其是弱耦合)的朋友们应该都知道有款软件叫preCICE或者mpCCI,本质上他们就是提供了基于网格单元的映射插值与基于KNN与RBF的节点插值。
这个被映射插值的物理量可能是各种各样的,可能是压力、应力、温度等等,用统一的方法(略有不同的实现方式,主要考虑是否要考虑守恒的物理量等因素)进行插值。而在这个过程中使用KNN就听起来很简单,最简单的思路就是全局遍历,比如从一个点云(每个点上都对应一些物理量),向另一片点云(或网格)进行搜索,那么这个搜索复杂度可是老高了。那么想着降低搜索的复杂度,其实也很简单,这就用上了我们之前讲的空间划分算法,尽可能的在更小的范围内进行搜索:
以下就是一段非常简单的python代码,快速的给出knn的检测:
from sklearn.neighbors import KDTree
tree = KDTree(all_nodes)
distances, indices = tree.query(query_point, k=3)
然后在找到这k个近邻的节点之后,我们就可以通过RBF方式进行插值,可能有朋友会问,这里为啥我们不用拉格朗日插值、线性插值等等,这个原因也很好理解,因为你找到的k近邻点不一定在空间中分布是啥样的,他们中间也没有网格连着。那RBF其实很好理解,可以理解为就是以这个网格节点为中心,然后沿着径向逐渐减小,最后随着离中心越远,逐渐缩减到0,也就是在插值中不再进行贡献,具体如下图所示:
然后诸如对一个物理量的插值就可以写成
其中 为第k个节点的径向基函数。那么通过上述的方式就可以实现两个区域基于节点数据的映射插值。大概长这样:
可能有熟悉神经网络的朋友们会觉得这玩意不是有限元吗,这里的概念咋跟神经网络里面那么多概念是重合的,其实答案就是:数学原理都差不多,学好数学吧!