捐赠我们 社区应用 会员列表 统计排行 邀请注册
主题 : 关于CFDRC用户编程的几点体会
liuhuafei 离线
级别: 高级会员
显示用户信息 
0  发表于: 2004-05-14   
倒序阅读   全看  

关于CFDRC用户编程的几点体会

管理提醒: 本帖被 wjjxlc 执行加亮操作(2008-05-28)
   这几天用了以下CFDRC的用户编程,本人不是CFDRC的官方用户,没受过正式培训,多数靠自己摸索,估计有些方法,非常笨拙,希望各位多多批评。
我先总结一部分,准备陆续贴出来,今天先贴一部分,下周在整理一些
liuhuafei 离线
级别: 高级会员
显示用户信息 
1  发表于: 2004-05-14   
全看  
下面就用户编程常用的几个方面谈谈自己的体会:

物性子程序:
主要有函数:udens udrhodp uvisc ucond ucph_from_t udiff_scalar uecond upermittivity等分别定义 密度 动力粘性系数 热传导系数 比热 电导率 磁导率等
这些函数的调用级别是 针对 每一个控制体,即cell级别
cfdrc在调用这些函数是
  遍历每一个Volume条件
                 遍历属于Voulme条件中每一个控制体Cell
                            CALL 物性函数(iopt,vc_index,..)
这些函数的参数 都有vc_index,表示Volume体积条件标识号(Volume Condition Index).
编程步骤:
1)采用get_var_index获取变量的标示号存储在全局变量中
2)采用get_vc_index获取区域的标识号存储在全局变量中
3)先判断体积条件标识号,是否是自己需要处理的体积标识号,如
  if(vc_index==ind_vc)
  注意vc_index为程序入口参数传入,ind_vc是用户在全局变量定义的,利用用户关心体积条件标识号为FLUID1的区域,可取得其标识号
  call get_vc_index(‘FLUID1’, ind_vc,error)
4)获取当前控制体的标识号 call get_active_cell_index(ind_ic,error),于ind_ic中
5)获取需要访问的其它变量,如温度t
    call get_value_one_cell(ind_t,ind_ic,t,error)
  ind_t为变量T的表示号
6)设置当前控制体的物性值
    cond=133.+0.1 *t
    call set_value_one_cell(ind_cond,ind_ic,cond,error)

下面是一段小的

!***********************************************************************
SUBROUTINE uvisc(iopt, vc_index)
! Include required global variables declared in cfdrc_user module.
  USE cfdrc_user
  USE cfdrc_user_access

  IMPLICIT NONE

  INTEGER(int_p), INTENT(IN) :: iopt, vc_index

! Declare required local variables here.
! USER VARIABLE DECLARATION BEGIN

  INTEGER(int_p) :: ind_ic
  REAL(real_p) :: t
  REAL(real_p) :: viscosity
  LOGICAL :: error = .FALSE.

! USER VARIABLE DECLARATION END

!-----------------------------------------------------------------------
! Start writing code here.
! USER CODE BEGIN

  CALL findindex()

  IF (vc_index == ind_vc1) THEN
    CALL get_active_cell_index(ind_ic, error)
    IF (ind_ic <= 0 .OR. error) STOP

    CALL get_value_one_cell(ind_t, ind_ic, t, error)
    IF (error) STOP

    viscosity = 1.846E-005 + 1.e-10 * t

    CALL set_value_one_cell(ind_visl, ind_ic, viscosity, error)
    IF (error) STOP

  ENDIF

! USER CODE END
  RETURN
END SUBROUTINE uvisc
!
!*********************************************************************
SUBROUTINE ucond(iopt, vc_index)
!DEC$ ATTRIBUTES DLLEXPORT :: ucond
*********************************************************************
! Include required global variables declared in cfdrc_user module.
  USE cfdrc_user
  USE cfdrc_user_access

  IMPLICIT NONE

  INTEGER(int_p), INTENT(IN) :: iopt, vc_index

! Declare required local variables here.

! USER VARIABLE DECLARATION BEGIN
  INTEGER(int_p) :: ind_ic
  REAL(real_p) :: t
  REAL(real_p) :: conduct
  LOGICAL :: error = .FALSE.

! USER VARIABLE DECLARATION END
!-----------------------------------------------------------------------
! Start writing code here.
! USER CODE BEGIN
  CALL findindex()

  IF (vc_index == ind_vc1) THEN
    CALL get_active_cell_index(ind_ic, error)
    IF (ind_ic <= 0 .OR. error) STOP

    CALL get_value_one_cell(ind_t, ind_ic, t, error)
    IF (error) STOP

    conduct = 0.0263 + 1.e-10 * t

    CALL set_value_one_cell(ind_cond, ind_ic, conduct, error)
    IF (error) STOP

  ENDIF

! USER CODE END
  RETURN
END SUBROUTINE ucond
!
realone 离线
级别: 普通会员
显示用户信息 
2  发表于: 2004-05-14   
全看  
厉害。

偶想用C++写UDF,楼主知道CFDRC的UDF dll中,export出的函数调用遵循的是什么规范呢,是PASCAL,stdcall抑或其他标准?
xlxue21 离线
级别: 初级会员
显示用户信息 
3  发表于: 2004-05-14   
全看  
楼主能不能就Fluent和CFDRC的各自特点做以简单介绍
偶原先学的Fortran77,而Fluent的UDF学要用C编写,感觉很不习惯,所以有转向CFDRC的打算,但是重新学一个软件并不是轻而易举的事,尤其是想要达到稍微熟练一点的程度

想了解一下这两个软件各自的优缺点
可能的话顺便对比一下Numeca
呵呵
要求有点过分,谢谢!
本人历年所获嘉奖总结:
   1985年4月29日,获小红花一朵,由大班赵奶奶亲自颁发;
   1998年6月1日,获进步最大奖一次,由刘老师发小本一个;
   2000年某月某日,获班篮球队新人奖,由张天光同学口头表扬;
   2001年12月18日,获南京电脑体育彩票一次,由帅小伙儿发奖金5元。
liuhuafei 离线
级别: 高级会员
显示用户信息 
4  发表于: 2004-05-15   
全看  
用户自定义边界:
由ubound(bc_index,var_index,face_index,xfc,yfc,zfc)定义
UBOUND被调用的方式:
  所有边界区域(遍历所有边界标识号)
     遍历所有变量(判断对变量是否需要子程序定义)
           该边界区域的所有边界面(遍历所用边界面标识号)
                        CALL UBOUND
即调用级别是针对每个边界面上每个变量

实施步骤:
1.首先用var_index判断正在处理的变量是否是用户需要设定的变量
2.用bc_index判断正在处理的边界区域是否是用户需要处理的边界区域
3.采用set_bc(value,error)设定当前face_index处的边界值

if(var_index .eq. ind_var) then
if(bc_index .eq. ind_bc) then
       value = ………
       CALL set_bc(value,error)
end if
end if

一个例子:
!********************************************************************* SUBROUTINE ubound(bc_index, var_index, face_index, xfc, yfc, zfc)
!DEC$ ATTRIBUTES DLLEXPORT :: ubound
!******* DO NOT REMOVE ABOVE LINE FOR MS WINDOWS OS ************
! copyright (c) 1998 cfd research corp. all rights reserved.
!
! purpose : set boundary value of the current boundary variable.
!
! inputs : bc_index Integer, global boundary index.
! var_index Integer, global variable index.
! face_index, global boundary face index.
! xfc Real, x coordinate of boundary face center.
! yfc Real, y coordinate of boundary face center.
! zfc Real, z coordinate of boundary face center.
!
!-----------------------------------------------------------------------

! Include required global variables declared in cfdrc_user module.
  USE cfdrc_user
  USE cfdrc_user_access

  IMPLICIT NONE

  ! Declaration of arguments of this subroutine.
  REAL(real_p), INTENT(IN) :: xfc, yfc, zfc

  INTEGER(int_p), INTENT(IN) :: bc_index, var_index, face_index

! Declare required local variables here.
! USER VARIABLE DECLARATION BEGIN
  LOGICAL :: error = .FALSE.
  REAL(real_p) uval
! USER VARIABLE DECLARATION END

!-----------------------------------------------------------------------
! Start writing code here.
! USER CODE BEGIN
  call findindex()

  IF(bc_index .EQ. ind_bc1) THEN
    IF(var_index .EQ. ind_u) THEN
      uval = 2.- yfc ** 2.
      call set_bc(uval,error)
      IF (error) STOP
    ELSE IF(var_index .EQ. ind_v) THEN
      uval = 0.
      call set_bc(uval,error)
      IF (error) STOP
    END IF
  ENDIF

! USER CODE END
  RETURN
END SUBROUTINE ubound
!
liuhuafei 离线
级别: 高级会员
显示用户信息 
5  发表于: 2004-05-15   
全看  
源项设置:
调用方式:
  所有的体积条件 ,判断是否需要自定义源项
         CALL USOURCE
实施步骤:
1.检查var_index是否是用户需要设定的变量
2.检查vc_index是否是用户需要处理的体积条件
       获得体积条件中的控制体数目
       遍历所有的控制体
     设定Su(i) Sp(i)
3. 调用add-source-terms函数

需要注意的是
USOURCE可能是CFDRC中写代码比较困难的一个,主要难点是需要自己定义SC SP两个数组,并且数组是动态分配大小的。此外源项SC的与通常我们用的单位体积源项不同,CFDRC采用的是绝对源项,即是我们通常用的SC乘上当前控制体的体积VOL。
下面对源项具体说明
我们通常所说的源项 S=S1+S2*Phi
在编程时,对于每个控制体Cell, S=S1*Vol + S2*Vol*Phi
在CFDRC编程时需要将 S1*VOL设定为 SC,将S2设定为SP

贴一个自己写的一段源项的实施代码。
附件: sources code.txt (3 K) 下载次数:20
liuhuafei 离线
级别: 高级会员
显示用户信息 
6  发表于: 2004-05-15   
全看  
引用
xlxue21 wrote:
楼主能不能就Fluent和CFDRC的各自特点做以简单介绍
偶原先学的Fortran77,而Fluent的UDF学要用C编写,感觉很不习惯,所以有转向CFDRC的打算,但是重新学一个软件并不是轻而易举的事,尤其是想要达到稍微熟练一点的程度

想了解一下这两个软件各自的优缺点
可能的话顺便对比一下Numeca
呵呵
要求有点过分,谢谢!


FLUENT本身功能非常强大,使用用户广,这一点不用说。但是我并不喜欢用FLUENT,主要原因是FLUENT 5后采用C语言来写UDF。我学习CFD最初是从学Pantankar和Spalding的交错网格的SIMPLE代码开始,后来又用过 Teach程序,Champion程序,最后用 Milovan的程序,直到自己将其改写成三维的多块结构化网格的求解器,一直是采用Fortran编程,一直沿用的是帝国理工大学Gosman和Spalding他们CFD的编程的思路。
虽然我在学CFD前,能非常熟练地写C C++代码,也常常帮别人开发用户界面程序,也曾经尝试过用C写CFD代码,但是写着写着就是没感觉。实际上我的观点是用C C++写CFD代码显得不专业,面向对象中的一些关于数据封装、继承、多态在CFD派不上多大用场,现在数据封装在一些CFD软件开始使用,虽然数据使用上更安全、但是用户使用起来并不方便,如果是我自己写的代码,就更没必要这样,为了访问某个数据费尽周折;而且使运行效率降低。
所以我常用的软件是STAR-cd,虽然star-cd的前处理功能不好,但是用户编程,非常习惯,核心数据都能方便访问,

例如在边界上设定边界值
在STAR-cd中:
  SUBROUTINE BCDEFI(SCALC(50),U,V,W,TE,ED,T,DEN,TURINT)
    ..........
  IF(IREG.NE.3) RETURN
  U0=1.
  U=U0*SIN(Y)
  RETURN
  END
在子程序中 U V W等能非常方便的引用
 
在FLUENT中
#include "udf.h"
DEFINE_PROFILE(inlet_x_velocity, /* function name  */
              thread,          /* thread          */
              nv)              /* variable number */
{
  face_t f;
  real x[ND_ND];

  /* loop over each of the faces of this zone */
  begin_f_loop (f,thread)
    {
      F_CENTROID(x,f,thread);
      F_PROFILE(f,thread,nv) = 20. - 20.*pow(x[1]/.0745, 2.);
    }
  end_f_loop (f,thread)
}
有我们不太熟悉的宏、FLUENT自己定义的数据类型face_t等

在AVL中
SUBROUTINE USEBND(k,mph)
INCLUDE 'comdp.inc'
INCLUDE 'com0.inc'

IF(IBC(1,ir)==1 .AND. icomp<=1) THEN
  DO ib=nsr(ir),ner(ir)
    UB(1,ib)=0.1
    VB(1,ib)=0.2
    WB(1,ib)=0.3
  END DO
END IF
在AVL中子程序中 U V W等其它变量能非常方便的引用

通常情况下,C C++相对于FORTRAN语言功能上更强,但是从CFD的角度讲,并不是因为FLUENT采用C语言,在用户编程上就有多强,因为C语言中很多被认为是强项的,如自定义数据类型,数据封装对于计算本身来说并不方便,并不是重要的,并不能形成优势。实际上用户编程的功能主要取决于软件公司开放程度,对于FLUENT,STAR-CD,AVL,CFX等这些软件在用户编程方面的功能差不多,基本上就是前面所说的边界设定,源项处理,自定义方程等功能,它们这些软件的开放性肯定与PHOENICS不一样。
但是从编程的,完全取决于用户自己的喜好和背景,像我这样热衷于FORTRAN的当然喜欢采用FORTRAN语言了。

对于CFDRC由于采用F90的面向对象设计技术,采用了 类设计,数据封装等技术,实际上CFDRC的用户编程更类似于 FLUENT,所以在CFDRC中,核心的数据不是直接访问,而是通过 类中方法来访问的,所以基本上都是先取得表示号,然后访问其值

下面给出一段CFDRC本身定义的一段代码
实际上module相当于C++的class

!*********************************************************************
module cfdrc_user_access
*********************************************************************
  use precision
  use dfwin, only : loadlibrary, getprocaddress, freelibrary
integer(i_p) :: user_lib_version = 2003, &
  数据定义部分                 
…………

  ! general access routines    相当于函数声明,或者类中的方法
  interface
    subroutine get_num_compositi*****(n_compos, error)
      use precision
      implicit none
      integer(i_p), intent(out) :: n_compos
      logical, intent(out) :: error
    end subroutine get_num_compositi*****

    subroutine get_num_species(n_spcs, error)
      use precision
      implicit none
      integer(i_p), intent(out) :: n_spcs
      logical, intent(out) :: error
    end subroutine get_num_species
……………………….
  end interface

  pointer(genPt1, get_num_compositi*****)  还用了指针
  pointer(genPt2, get_num_species)
  pointer(genPt3, get_species_name)
…………..

contains                                方法实施部分,相当于C++的IMPLENTATION部分

subroutine load_cfdrc_access_symbols
genPt1 = getprocaddress(exePtr, "GET_NUM_COMPOSITI*****"C)
  if (genPt1 == 0) then
    error_string = &
      'Unable to find subroutine GET_NUM_COMPOSITI***** in '// &
      cfdrc_exe(1:len_trim(cfdrc_exe))// &
      ' Contact CFDRC  for further details.'
    call user_info(iopt, error_string)
  endif

  genPt2 = getprocaddress(exePtr, "GET_NUM_SPECIES"C)
  if (genPt2 == 0) then
    error_string = &
      'Unable to find subroutine GET_NUM_SPECIES in '// &
      cfdrc_exe(1:len_trim(cfdrc_exe))// &
      ' Contact CFDRC  for further details.'
    call user_info(iopt, error_string)
  endif
end subroutine load_cfdrc_access_symbols

end module cfdrc_user_access
清空我的评分动态本帖最近评分记录: 共1条评分记录
xiaoshuai537 积分 +1 2010-09-15 liuhuafei老师,您好,我正在学基于TEACH的一个程序,希望得到您的帮助,谢谢,xiaoshuai_hust@qq.com
隐藏评分记录
sskkmmxxllpp 离线
级别: 高级会员
显示用户信息 
7  发表于: 2004-05-15   
全看  

太应该加分了,这才是学习任何软件的最高境界,希望老兄继续将自己的体会无私奉献出来。
xlxue21 离线
级别: 初级会员
显示用户信息 
8  发表于: 2004-05-16   
全看  
liuhuafei兄太强了!
赞一个!
本人历年所获嘉奖总结:
   1985年4月29日,获小红花一朵,由大班赵奶奶亲自颁发;
   1998年6月1日,获进步最大奖一次,由刘老师发小本一个;
   2000年某月某日,获班篮球队新人奖,由张天光同学口头表扬;
   2001年12月18日,获南京电脑体育彩票一次,由帅小伙儿发奖金5元。
liuhuafei 离线
级别: 高级会员
显示用户信息 
9  发表于: 2004-05-16   
全看  
CFDRC计算的结果
liuhuafei 离线
级别: 高级会员
显示用户信息 
10  发表于: 2004-05-16   
全看  
我自己编写的程序计算的结果
liuhuafei 离线
级别: 高级会员
显示用户信息 
11  发表于: 2004-05-16   
全看  
引用
realone wrote:
厉害。

偶想用C++写UDF,楼主知道CFDRC的UDF dll中,export出的函数调用遵循的是什么规范呢,是PASCAL,stdcall抑或其他标准?


你所讲的是C或c++写的DLL,确实有export的规则,CFDRC用的的Fortran 90语法,这个好像不是问题,只要在compaq fortran 中将项目类型指定成DLL就可。
但是如果你用c++写CFDRC的DLL,那就是个比较难的问题了??
liuhuafei 离线
级别: 高级会员
显示用户信息 
12  发表于: 2004-05-16   
全看  
引用
liuhuafei wrote:
10V
――――――――――
//| |//
//| |//
//| 电介质 |//
//| |//
//| |//
//|_______________|------|| 0V接地
//////////////////
r


图形有点变形, 顶面是100v,四周壁面是接地,
过路蚂蚁 离线
级别: 初级会员
显示用户信息 
13  发表于: 2005-04-08   
全看  
写得很好,谢谢
linzy96 离线
级别: 初级会员
显示用户信息 
14  发表于: 2005-04-24   
全看  
很好,值得学习
傲雪我的家,我们都爱她! <BR> 初次见面,多多关照
描述
快速回复

验证问题:
傲雪论坛成立于哪一年? 正确答案:2002年
按"Ctrl+Enter"直接提交