Rainyboy 发表于 2010-12-6 02:09

用TTM方法生成翼型网格(Python & MATLAB)

本帖最后由 Rainyboy 于 2010-12-6 03:27 编辑

为了练习Python,把以前拿MATLAB写过的这个算法重写了一遍,算是对Python在数值计算有一些体会了吧。原理见附件,程序入口点是CFDMesh.py,其实整个大流程就是一个迭代而已。
代码贴在下面,Python语义中很重要的一部分就是缩进……如果用“代码”功能的话就贴乱了,我还是用分割线吧。
附件里也有每个文件的压缩包。

第一次用Python写这种规模的数值程序,肯定有很多地方的实现过于罗嗦,还请大家不吝指正!


============代码文件分割线:CFDMesh.py=========================
# -*- coding: cp936 -*-
#用TTM方法生车贴体网格
#范雨 2010/12/5
import numpy as np;import matplotlib.pyplot as plt
from fCreatInitMesh import *;
from fPlotMesh import *;
from fAdjustBound import *;
from fPoint_Itera import *;
from fCheckConvergence import *;
if __name__ == '__main__':
    #-----------------------------
    #参数表
    #-----------------------------
    #根据结构的对称性,只储存和计算一半的网格
    #因此,周向分网数实际上是实际值的一半
    IM = 18;#实际周向分网数=IM*2
    JM = 21;#径向分网数
    L_C = 1;#弦长
    R_OUT = 2.5*L_C;#网格外径
    #生成初始网格
    (x,y)=CreatInitMesh(R_OUT,JM,IM);
    #画出初始网格
    PlotMesh(x,y,IM,JM,1);
    #准备迭代:准备储存当前步和推进步的空间
    y_next = np.zeros((JM,IM));
    x_next = np.zeros((JM,IM));
    y_curr = np.zeros((JM,IM));
    x_curr = np.zeros((JM,IM));
    y_curr[:,:] = y[:,:];
    x_curr[:,:] = x[:,:];
    #设置边界条件
    x_next = x_curr;
    x_next = x_curr;
    y_next = y_curr;
    y_next = y_curr;
    x_next[:,IM-1] = x_curr[:,IM-1];
    y_next[:,0] = y_curr[:,0];
    #x_next[:,0] = x_curr[:,0];#这个边界条件需要动态修正,在AdjustBound中进行
    y_next[:,IM-1] = y_curr[:,IM-1];
    #储存误差历程的向量
    MaxError = np.zeros((1,5000));
    re = 1;
    for n in range(0,500):
      #进一步调整边界条件
      AdjustBound(x_curr,y_curr,x_next,y_next,IM,JM);
      #迭代一步
      Point_Itera(x_curr,y_curr,x_next,y_next,IM,JM);
      #检查收敛
      (re , MaxError) = CheckConvergence(x_curr,y_curr,x_next,y_next,IM,JM);
      if re == 1:
            break;
      #递推
      x_curr[:,:] = x_next[:,:];
      y_curr[:,:] = y_next[:,:];
    #画出最终网格
    PlotMesh(x_next,y_next,IM,JM,2);
    #画出残差随迭代的变化
    fig = plt.figure(3);
    ax = fig.add_subplot(1,1,1);
    ax.plot(MaxError);
    plt.show();
============代码文件分割线:================================

============代码文件分割线:fCreatInitMesh.py========================
# -*- coding: cp936 -*-
#用TTM方法生车贴体网格
#范雨 2010/12/5
#子模块,用于生成初始网格
import numpy as np
from fFZeros import *
def CreatInitMesh(R_OUT,JM,IM):
    #翼型参数 y = p0*x^0.5 + p1*x + p2*x^2 + p3*x^3 + p4*x^4
    p0 = 0.2969;
    p1 = -0.1260;
    p2 = -0.3516;
    p3 = 0.2843;
    p4 = -0.1015;
    #直角坐标表示的点
    x = np.zeros((JM,IM));
    y = np.zeros((JM,IM));
    #极坐标表示的点
    r = np.zeros((JM,IM));
    thita = np.linspace(0,np.pi,IM);
    #得到最内层的点
    for i in range(0,IM-1):
      k1 = np.cos(thita);
      k2 = np.sin(thita);
      try:
            r = FZeros(y_s,(-0.5,10,0.5),(p0,p1,p2,p3,p4,k1,k2));
      except NoRootException ,e:
            print i;
            print "在所设置的区间" , e.ebound , "及参数表" , e.eparalist , "内没有根" ;
    r = 0.5;
    #得到最外层的点
    r = R_OUT;
    #插值得到中间的点
    for i in range(1,JM-1):
      r = (JM-i-1)*1.0/(JM-1)*r + (-i)*1.0/(1-JM)*r;
    #极坐标转换为直角坐标
    for i in range(0,JM):
      x = r * np.cos(thita) + 0.5;
      y = r * np.sin(thita);
    return (x,y);

def y_s((r,p0,p1,p2,p3,p4,k1,k2)):
    return p0*(k1*r+0.5)**0.5 + p1*(k1*r+0.5) + p2*(k1*r+0.5)**2 + p3*(k1*r+0.5)**3 + p4*(k1*r+0.5)**4 - k2*r;

if __name__ == '__main__':
    try:
      IM = 18;#实际周向分网数=IM*2
      JM = 21;#径向分网数
      L_C = 1;#弦长
      R_OUT = 2.5*L_C;#网格外径

      CreatInitMesh(R_OUT,JM,IM);
    except NoRootException ,e:
      print "在所设置的区间" , e.ebound , "及参数表" , e.eparalist , "内没有根" ;
============代码文件分割线:================================

============代码文件分割线:fPlotMesh.py========================
# -*- coding: cp936 -*-
#用TTM方法生车贴体网格
#范雨 2010/12/5
#子模块,画出网格
import matplotlib.pyplot as plt
import numpy as np
def PlotMesh(x,y,IM,JM,n):
    fig = plt.figure(n);
    ax = fig.add_subplot(1,1,1);
    for i in range(0,JM):
      ax.plot(x,y,color='blue');
      ax.plot(x,-y,color='blue');
    for i in range(0,IM):
      ax.plot(x[:,i],y[:,i],color='blue');
      ax.plot(x[:,i],-y[:,i],color='blue');
    plt.show();
============代码文件分割线:================================


============代码文件分割线:fZeros.py========================
# -*- coding: cp936 -*-
#牛顿法求一元函数在制定初值附近的根
#范雨 2010/12/5
def FZeros(func,bound,paralist):
    """对指定的一元函数在指定的点求导数值

      func   函数对象,其定义形式应为,(注意,该函数以一个 元组 为参数)
               test((x,p1,p2,p3,p4,...))
      bound    求根区间及初始值(x_min,x_max,x_init)
      paralist (p1,p2,p3,p4,...)
    """
    (x_min,x_max,x_init) = bound;
    root_last = x_init;
    root_now = x_init;
    while True:
      root_now = root_last - func((root_last,) + paralist)/diff(func,root_last,paralist);
      if abs(root_last - root_now) <= 1e-4:
            break;
      if root_now >= x_min and root_now <= x_max:
            root_last = root_now;
      else:
            raise NoRootException(bound,paralist);
    return root_now;

def diff(func,x,paralist):
    """对指定的一元函数在指定的点求导数值

      func   函数对象,其定义形式应为,(注意,该函数以一个 元组 为参数)
               test((x,p1,p2,p3,p4,...))
      x      自变量的值
      paralist (p1,p2,p3,p4,...)
    """
    dx = 1e-8;
    return (func((x + dx,) + paralist) - func((x - dx,) + paralist))/(2*dx);

class NoRootException(Exception):
    """求根过程自定义的异常"""
    def __init__(Self,bound,paralist):
      Exception.__init__(Self);
      Self.ebound = bound;
      Self.eparalist = paralist;

if __name__ == '__main__':
    def test((x,p1,p2,p3)):
      y = p1*x**2 + p2*x + p3;
      return y;
    try:
      print FZeros(test,(5,10,6),(1,-4,3));
    except NoRootException ,e:
      print "在所设置的区间" , e.ebound , "及参数表" , e.eparalist , "内没有根" ;
============代码文件分割线:================================


============代码文件分割线:fAdjustBound.py========================
# -*- coding: cp936 -*-
#用TTM方法生车贴体网格
#范雨 2010/12/5
#子函数 用于动态调整边界条件
def AdjustBound(x_curr,y_curr,x_next,y_next,IM,JM):
    i=0;
    for j in range(1,JM-1):
      pxpI = (x_curr-x_curr)/2;
      pxpJ = (x_curr-x_curr)/2;
      pypI = (y_curr+y_curr)/2;
      pypJ = (y_curr-y_curr)/2;
      a = pxpI**2 + pypI**2;
      b = pxpI*pxpJ + pypI*pypJ;
      c = pxpJ**2 + pypJ**2;
      x_next= (a*(x_curr+x_curr)-b*(x_curr-x_curr-x_curr+x_curr)/2 + c*(x_curr+x_curr))/(a+c)/2;
    i=IM-1;
    for j in range(1,JM-1):
      pxpI = (x_curr-x_curr)/2;
      pxpJ = (x_curr-x_curr)/2;
      pypI = (y_curr+y_curr)/2;
      pypJ = (y_curr-y_curr)/2;
      a = pxpI**2 + pypI**2;
      b = pxpI*pxpJ + pypI*pypJ;
      c = pxpJ**2 + pypJ**2;
      x_next= (a*(x_curr+x_curr)-b*(x_curr-x_curr-x_curr+x_curr)/2 + c*(x_curr+x_curr))/(a+c)/2;
============代码文件分割线:================================

============代码文件分割线:fCheckConvergence.py========================
# -*- coding: cp936 -*-
#用TTM方法生车贴体网格
#范雨 2010/12/5
#子函数,检查收敛
import numpy as np;
def CheckConvergence(x_curr,y_curr,x_next,y_next,IM,JM):
    lim_max_error = 1e-5;
    max_error = np.max(np.abs(x_curr[:,:]-x_next[:,:])) + np.max(np.abs(y_curr[:,:]-y_next[:,:]));
    re = 1;
    if max_error < lim_max_error:
      re = 1;
    else:
      re = 0;
    print max_error;
    return (re , max_error);
============代码文件分割线:================================





============代码文件分割线:fPoint_Itera.py========================
# -*- coding: cp936 -*-
#用TTM方法生车贴体网格
#范雨 2010/12/5
#子函数,用于迭代一步
def Point_Itera(x_curr,y_curr,x_next,y_next,IM,JM):
    for i in range(1,IM-1):
      for j in range(1,JM-1):
            #得到四个偏导数
            pxpI = (x_curr-x_curr)/2;
            pxpJ = (x_curr-x_curr)/2;
            pypI = (y_curr-y_curr)/2;
            pypJ = (y_curr-y_curr)/2;
            a = pxpI**2 + pypI**2;
            b = pxpI*pxpJ + pypI*pypJ;
            c = pxpJ**2 + pypJ**2;
            x_next= (a*(x_curr+x_curr)-b*(x_curr-x_curr-x_curr+x_curr)/2 + c*(x_curr+x_curr))/(a+c)/2;
            y_next= (a*(y_curr+y_curr)-b*(y_curr-y_curr-y_curr+y_curr)/2 + c*(y_curr+y_curr))/(a+c)/2;
============代码文件分割线:================================

初始网格:

最终网格:




误差随迭代变化:







Rainyboy 发表于 2010-12-6 03:06

本帖最后由 Rainyboy 于 2010-12-6 03:08 编辑

MATLAB版的实现更全,一共实现了8种迭代算法,并比较了各种算法的性能。
%方法
nMethod = 7;
% nMethod = 0;%Jacobi点迭代
% nMethod = 1;%Jacobi线迭代
% nMethod = 2; %Jacobi点迭代 + 超松弛 (不可行,计算结果会发散,此处作为对比)
% nMethod = 3;%Jacobi线迭代 + 超松弛(不可行,计算结果会发散,此处作为对比)
% nMethod = 4;%Guass-Siedel点迭代
% nMethod = 5;%Guass-Siedel线迭代
% nMethod = 6;%Guass-Siedel点迭代 + 超松弛
% nMethod = 7;%Guass-Siedel线迭代 + 超松弛


woai3181 发表于 2011-4-21 15:27

本帖最后由 woai3181 于 2011-4-21 15:28 编辑

好像不错,但下载不了。谢谢分享

woai3181 发表于 2011-4-21 15:32

能不能让我下载下你的MATLAB版TTM算法,我的权限不够下载。万分感谢!

唯有时光 发表于 2011-9-26 23:32

值得学习的好贴~~

lika 发表于 2012-3-27 12:34

学习了~~

李七牛 发表于 2012-9-18 15:13

向楼主致敬











static/image/common/sigline.gif
济宁:wangzhan678.com天泰电子:aizk007.com

ljz 发表于 2012-11-3 13:12

{:{39}:}

clarkww 发表于 2012-12-19 14:47

非常有用啊,感谢分享!

yunze 发表于 2013-5-6 07:51

好东西,来看看

liu3330 发表于 2014-3-17 09:07

没权限,不能下载怎么办

epistemer 发表于 2014-4-17 21:22

这是什么,翼型?

吴克烈次帅 发表于 2015-7-11 12:50

干货啊,楼主好人

eggtor 发表于 2015-7-11 14:37

本帖最后由 eggtor 于 2015-7-11 14:40 编辑

你好,请问能否给我发一下您的TTM法划分翼型外流场网格的matlab代码,我没有权限下载764261405@qq.com

吴克烈次帅 发表于 2015-7-12 12:27

没权限,不能下载
页: [1] 2
查看完整版本: 用TTM方法生成翼型网格(Python & MATLAB)