首页/文章/ 详情

接触基础知识:调整初始穿透的接触面

20天前浏览44

在很多模型中,划分完网格的两个物体都存在初始穿透,这是大体出于两个原因:

  1. 本来的3D模型就是穿透的,常见于螺栓处,因为3D模型很多时候螺纹并不是直接画出来,而是用外径画个圆柱体
  2. 3D模型不 穿透,但是划分完网格,由于网格的离散造成网格单元直接穿透。

这个时候,如果恰巧这两个”穿透“的物体,我们又设置了接触,就会造成过大的应力,所以很多商业软件中都提供了”调整“功能,在Abaqus中用ADJUST表示,以消除初始的穿透。

此逻辑在定义接触和定义绑定Tie的时候均可以采用,在Abaqus中设置方式分别如下: 



这样呢,程序在真正计算前就会有个预处理的流程,将这些定义接触的地方的初始穿透量给消除掉,具体消除的方法也很容易理解,那就是:沿着法向方向将穿透的从面节点推回到刚好不 穿透的位置。那么很多朋友就会问了,这个法向方向,对于两个平面还好说,对于不是平的面,是哪里的法向方向呢?Abaqus中采用了如下的方式,仔细想一下会发现非常符合点对面(NTS)和面对面(STS)两种算法的计算逻辑:

  1. 对于点对面,采用主面的法向方向
  2. 对于面对面,采用从面法向方向
     具体如下图所示,其中圆柱体为主面,左边是面对面算法的调整方式,右边面为点对面算法的调整方式。   
     

     

通过这种方式,这些人为的初始穿透就会在计算之前被解决,避免由于设置了接触且有初始穿透造成的应力过大的情况,避免被程序误认为这是一个过盈配合的过程,而相反对于真正想进行过盈配合计算的地方,只要不这么设置就好了。



来源:大狗子说数值模拟
Abaqus螺栓
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2025-07-17
最近编辑:20天前
大狗子说数值模拟
博士 传播国际一流的数值模拟算法
获赞 10粉丝 23文章 69课程 0
点赞
收藏
作者推荐

有限元基础知识:如何计算OBB包围盒

之前已经讲过AABB的编码实现,今天给大家讲一下OBB的编码实现,与AABB的编码不同,OBB会更紧贴物体,对于有限元接触仿真来说,会更贴近我们这一团网格,所以可以在前期搜索的时候更好的进行筛选。然而,OBB的计算会相对繁琐很多请看下边PCA(PrincipalComponentAnalysis)算法找到一堆节点的主轴首先找到一堆节点的的中心点其中为网格节点的坐标,具体C++代码如下usingpoint3D=std::array<double,3>;voidfindCentroid(conststd::vector<point3D>&pts,point3D&centroid){intnumber=pts.size();centroid[0]=centroid[1]=centroid[2]=0.0;for(inti=0;i<number;i++){centroid[0]+=pts[i][0];centroid[1]+=pts[i][1];centroid[2]+=pts[i][2];}centroid[0]/=n;centroid[1]/=n;centroid[2]/=n;}在得到了中心点坐标后,我们计算这一群节点与中心点的协方差矩阵,这个东西,大家顾名思义,可以理解成,这一群节点相较之这个节点有多分散,具体的算法如下这个代码也很好写,cpp代码如下voidcomputeCovariance(conststd::vector<point3D>&pts){point3Dcentroid;findCentroid(pts,centroid);std::array<point3D,3>covMat{0};for(constauto&pt:pts){doubledeltax=pt[0]-centroid[0];doubledeltay=pt[1]-centroid[1];doubledeltaz=pt[2]-centroid[2];covMat[0][0]+=deltax*deltax;covMat[1][1]+=deltay*deltay;covMat[2][2]+=deltaz*deltaz;covMat[0][1]+=deltax*deltay;covMat[0][2]+=deltax*deltaz;covMat[1][2]+=deltay*deltaz;}for(inti=0;i<3;++i){for(intj=0;j<3;++j){covMat[i][j]/=pts.size();}}covMat[1][0]=covMat[0][1];covMat[2][0]=covMat[0][2];covMat[2][1]=covMat[1][2];}然后我们通过提取协方差矩阵的特征向量,找到主轴,这个提取特征值的过程我们可以直接调用矩阵求解库中一般都有的特征值求解函数,或者由于这就是个矩阵的特征向量提取问题,我们可也可以自己写个更简单高效的[1],这里代码略,大家在很多地方都可以查到,大体上有3种写法,分列如下。voideigenMat33(constMat33&matrix,Mat33&eigenvectors,point3D&eigenvalues){//1.采用数学库比如Eigen直接进行计算//2.采用迭代求解特征值、特征向量//3.3x3矩阵特征值有解析求法,实现一下就行了}然后我们就得到了特征值与特征向量,这个特征向量3个数据方差最大的方向,也就是能找到的OBB的两两相对面的方向,现在我们终于可以构造OBB了,非常简单,其实就是将中点到各点的连线往这3个轴上进行投影,而投影嘛就是点乘,大家就记住这个操作就行了,然后简简单单的找个各个方向的最大值最小值,OBB就呼之欲出了,C++代码如下structOBB{Mat33axes;point3Dcenter;point3DhalfExtent;//半轴长};OBBcomputeOBB(conststd::vector<point3D>&pts,constMat33&eigenvectors){OBBobb;obb.axes[0]=eigenvectors[0];//最大特征值对应方向obb.axes[1]=eigenvectors[1];obb.axes[2]=eigenvectors[2];//计算各轴投影范围Vec3maxProj{-FLT_MAX,-FLT_MAX,-FLT_MAX};Vec3minProj{FLT_MAX,FLT_MAX,FLT_MAX};for(constauto&pt:pts){point3Ddir={pt[0],pt[1],pt[2]};for(inti=0;i<3;++i){doubleproj=dot(dir,obb.axes[i]);maxProj[i]=std::max(maxProj[i],proj);minProj[i]=std::min(minProj[i],proj);}}//计算中心点和半长obb.halfExtent={(maxProj[0]-minProj[0])/2.0,(maxProj[1]-minProj[1])/2.0,(maxProj[2]-minProj[2])/2.0};for(inti=0;i<3;i++){obb.center+=0.5*(maxProj[0]+maxProj[0])*obb.axes[i];}returnobb;}以上的代码就通过3个方向的投影计算了各个方向的半轴长度,与OBB的中心,注意哦,这里OBB的中心并不是刚刚计算出来的那个,一个简单的案例就是下边这个三角形:就这样我们就得到了一片Mesh的OBB,然而这种方法其实在有限元中用的不多,大家可以看到这个计算OBB的过程已经很繁琐了,然而其在游戏、CAD中用的还是不少的,但本着大家学就有用的思想,技多不压身,后面我可以单独讲一讲为啥他们在这些行业会有用。另外就是大家可能会在别的地方看到不同的OBB计算方法,但是基本思想是一致的,但是OBB的计算方法如果展开说我可以直接开一系列,最常用的一个变形就是先计算一堆节点的凸包(convexhull)再用其来计算OBB,但既然我还没讲过convexhull先就此略过,以后再补。然后还有更麻烦的呢,OBB的接触检测又需要用到一个算法,分离轴定理(SAT),其实也可以直接用GJK算法,这些也挺繁琐,有待下回分解。参考文献:[1]Siddique,AbuBakar,andTariqA.Khraishi.“EigenvaluesandEigenvectorsfor3x3SymmetricMatrices:AnAnalyticalApproach.”JournalofAdvancesinMathematicsandComputerScience35.7(2020):106-118来源:大狗子说数值模拟

未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈