fortran - 悲催的科学匠人 - 冷水's blog

[zz]FORTRAN版非递归快速排序

在二叉树离散网格单元时,最初使用递归的,但是网格单元到百万量级时,排序程序就出错了。怀疑是递归耗尽系统堆栈的问题,搜到一个非递归版本:  http://www.fortran.com/fortran/quick_sort2.f   百万量级也不是问题了。

 

      PROGRAM test_nrqsort
      REAL,ALLOCATABLE :: array(:)
      INTEGER,ALLOCATABLE :: idx(:)
      INTEGER N,i
      INTEGER,PARAMETER :: seed = 86456
      
      !READ(*,*) N
      N = 5000000
      ALLOCATE(array(N),idx(N))
      CALL srand(seed)
      DO i=1,N; 
         array(i) = rand()
      ENDDO
      WRITE(*,*) 'sorting'
      CALL SORTRX(N,array,idx)
      !DO i=1,N
      !  WRITE(*,*) array(idx(i))
      !ENDDO
      DO i=2,N
      IF(array(idx(i)) .lt. array(idx(i-1)) ) THEN
        WRITE(*,*) 'error', array(idx(i)), array(idx(i-1))
      ENDIF
      ENDDO
      DEALLOCATE(array,idx)
      END

C From Leonard J. Moss of SLAC:

C Here's a hybrid QuickSort I wrote a number of years ago.  It's
C based on suggestions in Knuth, Volume 3, and performs much better
C than a pure QuickSort on short or partially ordered input arrays.  

      SUBROUTINE SORTRX(N,DATA,INDEX)
C===================================================================
C
C     SORTRX -- SORT, Real input, indeX output
C
C
C     Input:  N     INTEGER
C             DATA  REAL
C
C     Output: INDEX INTEGER (DIMENSION N)
C
C This routine performs an in-memory sort of the first N elements of
C array DATA, returning into array INDEX the indices of elements of
C DATA arranged in ascending order.  Thus,
C
C    DATA(INDEX(1)) will be the smallest number in array DATA;
C    DATA(INDEX(N)) will be the largest number in DATA.
C
C The original data is not physically rearranged.  The original order
C of equal input values is not necessarily preserved.
C
C===================================================================
C
C SORTRX uses a hybrid QuickSort algorithm, based on several
C suggestions in Knuth, Volume 3, Section 5.2.2.  In particular, the
C "pivot key" [my term] for dividing each subsequence is chosen to be
C the median of the first, last, and middle values of the subsequence;
C and the QuickSort is cut off when a subsequence has 9 or fewer
C elements, and a straight insertion sort of the entire array is done
C at the end.  The result is comparable to a pure insertion sort for
C very short arrays, and very fast for very large arrays (of order 12
C micro-sec/element on the 3081K for arrays of 10K elements).  It is
C also not subject to the poor performance of the pure QuickSort on
C partially ordered data.
C
C Created:  15 Jul 1986  Len Moss
C
C===================================================================
 
      INTEGER   N,INDEX(N)
      REAL      DATA(N)
 
      INTEGER   LSTK(31),RSTK(31),ISTK
      INTEGER   L,R,I,J,P,INDEXP,INDEXT
      REAL      DATAP
 
C     QuickSort Cutoff
C
C     Quit QuickSort-ing when a subsequence contains M or fewer
C     elements and finish off at end with straight insertion sort.
C     According to Knuth, V.3, the optimum value of M is around 9.
 
      INTEGER   M
      PARAMETER (M=9)
 
C===================================================================
C
C     Make initial guess for INDEX
 
      DO 50 I=1,N
         INDEX(I)=I
   50    CONTINUE
 
C     If array is short, skip QuickSort and go directly to
C     the straight insertion sort.
 
      IF (N.LE.M) GOTO 900
 
C===================================================================
C
C     QuickSort
C
C     The "Qn:"s correspond roughly to steps in Algorithm Q,
C     Knuth, V.3, PP.116-117, modified to select the median
C     of the first, last, and middle elements as the "pivot
C     key" (in Knuth's notation, "K").  Also modified to leave
C     data in place and produce an INDEX array.  To simplify
C     comments, let DATA[I]=DATA(INDEX(I)).
 
C Q1: Initialize
      ISTK=0
      L=1
      R=N
 
  200 CONTINUE
 
C Q2: Sort the subsequence DATA[L]..DATA[R].
C
C     At this point, DATA[l] <= DATA[m] <= DATA[r] for all l < L,
C     r > R, and L <= m <= R.  (First time through, there is no
C     DATA for l < L or r > R.)
 
      I=L
      J=R
 
C Q2.5: Select pivot key
C
C     Let the pivot, P, be the midpoint of this subsequence,
C     P=(L+R)/2; then rearrange INDEX(L), INDEX(P), and INDEX(R)
C     so the corresponding DATA values are in increasing order.
C     The pivot key, DATAP, is then DATA[P].
 
      P=(L+R)/2
      INDEXP=INDEX(P)
      DATAP=DATA(INDEXP)
 
      IF (DATA(INDEX(L)) .GT. DATAP) THEN
         INDEX(P)=INDEX(L)
         INDEX(L)=INDEXP
         INDEXP=INDEX(P)
         DATAP=DATA(INDEXP)
      ENDIF
 
      IF (DATAP .GT. DATA(INDEX(R))) THEN
         IF (DATA(INDEX(L)) .GT. DATA(INDEX(R))) THEN
            INDEX(P)=INDEX(L)
            INDEX(L)=INDEX(R)
         ELSE
            INDEX(P)=INDEX(R)
         ENDIF
         INDEX(R)=INDEXP
         INDEXP=INDEX(P)
         DATAP=DATA(INDEXP)
      ENDIF
 
C     Now we swap values between the right and left sides and/or
C     move DATAP until all smaller values are on the left and all
C     larger values are on the right.  Neither the left or right
C     side will be internally ordered yet; however, DATAP will be
C     in its final position.
 
  300 CONTINUE
 
C Q3: Search for datum on left >= DATAP
C
C     At this point, DATA[L] <= DATAP.  We can therefore start scanning
C     up from L, looking for a value >= DATAP (this scan is guaranteed
C     to terminate since we initially placed DATAP near the middle of
C     the subsequence).
 
         I=I+1
         IF (DATA(INDEX(I)).LT.DATAP) GOTO 300
 
  400 CONTINUE
 
C Q4: Search for datum on right <= DATAP
C
C     At this point, DATA[R] >= DATAP.  We can therefore start scanning
C     down from R, looking for a value <= DATAP (this scan is guaranteed
C     to terminate since we initially placed DATAP near the middle of
C     the subsequence).
 
         J=J-1
         IF (DATA(INDEX(J)).GT.DATAP) GOTO 400
 
C Q5: Have the two scans collided?
 
      IF (I.LT.J) THEN
 
C Q6: No, interchange DATA[I] <--> DATA[J] and continue
 
         INDEXT=INDEX(I)
         INDEX(I)=INDEX(J)
         INDEX(J)=INDEXT
         GOTO 300
      ELSE
 
C Q7: Yes, select next subsequence to sort
C
C     At this point, I >= J and DATA[l] <= DATA[I] == DATAP <= DATA[r],
C     for all L <= l < I and J < r <= R.  If both subsequences are
C     more than M elements long, push the longer one on the stack and
C     go back to QuickSort the shorter; if only one is more than M
C     elements long, go back and QuickSort it; otherwise, pop a
C     subsequence off the stack and QuickSort it.
 
         IF (R-J .GE. I-L .AND. I-L .GT. M) THEN
            ISTK=ISTK+1
            LSTK(ISTK)=J+1
            RSTK(ISTK)=R
            R=I-1
         ELSE IF (I-L .GT. R-J .AND. R-J .GT. M) THEN
            ISTK=ISTK+1
            LSTK(ISTK)=L
            RSTK(ISTK)=I-1
            L=J+1
         ELSE IF (R-J .GT. M) THEN
            L=J+1
         ELSE IF (I-L .GT. M) THEN
            R=I-1
         ELSE
C Q8: Pop the stack, or terminate QuickSort if empty
            IF (ISTK.LT.1) GOTO 900
            L=LSTK(ISTK)
            R=RSTK(ISTK)
            ISTK=ISTK-1
         ENDIF
         GOTO 200
      ENDIF
 
  900 CONTINUE
 
C===================================================================
C
C Q9: Straight Insertion sort
 
      DO 950 I=2,N
         IF (DATA(INDEX(I-1)) .GT. DATA(INDEX(I))) THEN
            INDEXP=INDEX(I)
            DATAP=DATA(INDEXP)
            P=I-1
  920       CONTINUE
               INDEX(P+1) = INDEX(P)
               P=P-1
               IF (P.GT.0) THEN
                  IF (DATA(INDEX(P)).GT.DATAP) GOTO 920
               ENDIF
            INDEX(P+1) = INDEXP
         ENDIF
  950    CONTINUE
 
C===================================================================
C
C     All done
 
      END

PLOT3D文件格式[ZZ]

http://hi.baidu.com/necrohan/blog/item/4997711f294102fde0fe0b8e.html

 

其实早已熟悉,只是借来存档一下。此外,以前不知iblank的unformatted格式写法,这个博文居然有。

 

 

PLOT3D文件格式
 
 
FLOW3D可以导出的数据格式有限,说明中说支持tecplot,但是是需要tecplot插件的,而且要360版本才行,找了2个插件可是不能用,而且插件的功能好像很有限。
PLOT3D格式的数据可以在后处理时导出,为此查了一下PLOT3D格式的数据,实在不行再转为tecplot格式的数据。

PLOT3D 数据格式
PLOT3D数据格式源于NASA,广泛用于规则网格的CFD数据文件。PLOT3D文件可以是ASCII, 也可是Fortran unformatted 或 C binary形式。
PLOT3D文件分为网格文件(XYZ 文件), 空气动力学结果文件 (Q 文件)和通用结果文件(函数文件 + 函数名称文件)。网格文件中可加入所谓的IBlank参数。

IBlank参数的定义:
IBlank是在每一网格点上给出的一个正数值,定义如下:
0 - 计算域之外,非流体点
1 - 正常点
2 - 固面边界点
负数 - 分块网格界面点,其数值为相邻网格块的块号

以下为各文件使用FORTRAN读入的语句,所有文件均为无格式文件。

网格文件(XYZ文件):

XYZ 文件, 单块(single-block):
READ(IUNIT) IMAX,JMAX,KMAX
READ(IUNIT) (((X(I,J,K),I=1,IMAX),J=1,JMAX),K=1,KMAX),&
            (((Y(I,J,K),I=1,IMAX),J=1,JMAX),K=1,KMAX),&
            (((Z(I,J,K),I=1,IMAX),J=1,JMAX),K=1,KMAX)

XYZ 文件, 单块(single-block), 加 IBlank:
READ(IUNIT) IMAX,JMAX,KMAX
READ(IUNIT) (((X(I,J,K),I=1,IMAX),J=1,JMAX),K=1,KMAX),&
            (((Y(I,J,K),I=1,IMAX),J=1,JMAX),K=1,KMAX),&
            (((Z(I,J,K),I=1,IMAX),J=1,JMAX),K=1,KMAX),&
            (((IBLANK(I,J,K),I=1,IMAX),J=1,JMAX),K=1,KMAX)

XYZ 文件, 二维, 单块(single-block):
READ(IUNIT) IMAX,JMAX
READ(IUNIT) ((X(I,J),I=1,IMAX),J=1,JMAX),&
            ((Y(I,J),I=1,IMAX),J=1,JMAX)

XYZ 文件, 多块(multi-block)
READ(IUNIT) NBLOCK
READ(IUNIT) (IMAX(N),JMAX(N),KMAX(N),N=1,NBLOCK)
DO N=1,NBLOCK
READ(IUNIT) (((X(I,J,K),I=1,IMAX(N)),J=1,JMAX(N)),K=1,KMAX(N)),&
            (((Y(I,J,K),I=1,IMAX(N)),J=1,JMAX(N)),K=1,KMAX(N)),&
            (((Z(I,J,K),I=1,IMAX(N)),J=1,JMAX(N)),K=1,KMAX(N))
ENDDO

XYZ 文件, 多块(multi-block), 加 IBlank:
READ(IUNIT) NBLOCK
READ(IUNIT) (IMAX(N),JMAX(N),KMAX(N),N=1,NBLOCK)
DO N=1,NBLOCK
READ(IUNIT) (((X(I,J,K),I=1,IMAX(N)),J=1,JMAX(N)),K=1,KMAX(N)),&
            (((Y(I,J,K),I=1,IMAX(N)),J=1,JMAX(N)),K=1,KMAX(N)),&
            (((Z(I,J,K),I=1,IMAX(N)),J=1,JMAX(N)),K=1,KMAX(N)),&
            (((IBLANK(I,J,K),I=1,IMAX(N)),J=1,JMAX(N)),K=1,KMAX(N))
ENDDO

XYZ 文件, 二维, 多块(multi-block)
READ(IUNIT) NBLOCK
READ(IUNIT) (IMAX(N),JMAX(N),N=1,NBLOCK)
DO N=1,NBLOCK
READ(IUNIT) ((X(I,J),I=1,IMAX(N)),J=1,JMAX(N)),&
            ((Y(I,J),I=1,IMAX(N)),J=1,JMAX(N))
ENDDO

空气动力学结果文件 (Q 文件)(Q 文件定义过窄,现已很少使用。):

Q 文件专为外流空气动力学设计,对三维流动,数组变量如下:
Q1 - 无量纲 密度
Q2 - 无量纲 X-动量
Q3 - 无量纲 Y-动量
Q4 - 无量纲 Z-动量
Q5 - 无量纲 总能
另加4个参数:
FSMACH - 自由流马赫数
ALPHA - 攻角
RE     - 雷诺数
TIME   - 时间

Q 文件, 单块(single-block):
READ(IUNIT) IMAX,JMAX,KMAX
READ(IUNIT) FSMACH,ALPHA,RE,TIME
READ(IUNIT) ((((Q(I,J,K,M),I=1,IMAX),J=1,JMAX),K=1,KMAX),M=1,5)

Q 文件, 二维, 单块(single-block):
READ(IUNIT) IMAX,JMAX
READ(IUNIT) FSMACH,ALPHA,RE,TIME
READ(IUNIT) (((Q(I,J,M),I=1,IMAX),J=1,JMAX),M=1,4)

Q 文件, 多块(multi-block):
READ(IUNIT) NBLOCK
READ(IUNIT) (IMAX(N),JMAX(N),KMAX(N),N=1,NBLOCK)
DO N=1,NBLOCK
READ(IUNIT) FSMACH,ALPHA,RE,TIME
READ(IUNIT)((((Q(I,J,K,M),I=1,IMAX(N)),J=1,JMAX(N)),K=1,KMAX(N)),M=1,5)
ENDDO

Q 文件定义过窄,现已很少使用。大多CFD工作者使用通用结果文件,即
所谓的函数文件(function file)。函数文件中可定义任意数量的数组变量,
其名称在另一函数名称文件(function name file)中给出。

函数文件:
函数文件, 单块(single-block):
READ(IUNIT) IMAX,JMAX,KMAX
READ(IUNIT) ((((F(I,J,K,M),I=1,IMAX),J=1,JMAX),K=1,KMAX),M=1,NFUN)

函数文件, 二维, 单块(single-block):
READ(IUNIT) IMAX,JMAX
READ(IUNIT) (((F(I,J,M),I=1,IMAX),J=1,JMAX),M=1,NFUN)

函数文件, 多块(multi-block):
READ(IUNIT) NBLOCK
READ(IUNIT) (IMAX(N),JMAX(N),KMAX(N),N=1,NBLOCK)
DO N=1,NBLOCK
READ(IUNIT) ((((F(I,J,K,M),I=1,IMAX(N)),J=1,JMAX(N)),K=1,KMAX(N)),M=1,NFUN)
ENDDO

函数名称文件:
函数名称文件是一ASCII文件,列有函数文件中数组变量的对应名称。以下为一例子:
density
pressure
u;velocity vector
v
w
temperature
turbulence energy
...
...

注意事项:
1 名称的数量和排列次序与函数文件中数组变量相同。
2 分割号 ";" 表示向量行的开始。";"之右为向量名,";"之左为X分量。其下两行为Y分量和Z分量。

http://www.grc.nasa.gov/WWW/wind/valid/plot3d.html
下面例子假设网格文件句柄为7,结果文件句柄为8。

2D, Whole, Formatted, Single-Block Grid and Solution

      parameter ( imax = 100 )
      parameter ( jmax = 100 )

      integer i
      integer j
      integer m
      integer n
      integer ni
      integer nj

      real mach   ! freestream Mach number
      real alpha ! freestream angle-of-attack
      real reyn   ! freestream Reynolds number
      real time   ! time

      real x(imax,jmax)
      real y(imax,jmax)

      real q(imax,jmax,4)

      open ( unit=7, form='formatted', file='2D.x' )
      open ( unit=8, form='formatted', file='2D.q' )

      read(7,*) ni, nj
      read(7,*)
     &    (( x(i,j), i=1,ni), j=1,nj),
     &    (( y(i,j), i=1,ni), j=1,nj)

      read(8,*) ni, nj
      read(8,*) mach, alpha, reyn, time
      read(8,*) ((( q(i,j,n), i=1,ni), j=1,nj), n=1,4)

3D, Whole, Unformatted, Multi-Block Grid and Solution

      parameter ( imax = 100 )
      parameter ( jmax = 100 )
      parameter ( kmax = 100 )
      parameter ( nbmax = 10 )

      integer i
      integer j
      integer m
      integer n
      integer nblocks
      integer ni (nbmax)
      integer nj (nbmax)
      integer nk (nbmax)

      real mach   ! freestream Mach number
      real alpha ! freestream angle-of-attack
      real reyn   ! freestream Reynolds number
      real time   ! time

      real x(imax,jmax,kmax,nbmax)
      real y(imax,jmax,kmax,nbmax)
      real z(imax,jmax,kmax,nbmax)

      real q(imax,jmax,kmax,nbmax,5)

      open ( unit=7, form='unformatted', file='3D.x' )
      open ( unit=8, form='unformatted', file='3D.q' )

      read(7) nblocks
      read(7) ( ni(m), nj(m), nk(m), m = 1, nblocks )
      do m = 1, nblocks
        read(7)
     &    ((( x(i,j,k,m), i=1,ni(m)), j=1,nj(m)), k=1,nk(m)),
     &    ((( y(i,j,k,m), i=1,ni(m)), j=1,nj(m)), k=1,nk(m)),
     &    ((( z(i,j,k,m), i=1,ni(m)), j=1,nj(m)), k=1,nk(m))
      enddo

      read(8) nblocks
      read(8) ( ni(m), nj(m), nk(m), m = 1, nblocks )
      do m = 1, nblocks
        read(8) mach, alpha, reyn, time
        read(8)
     &    (((( q(i,j,k,m,n), i=1,ni(m)), j=1,nj(m)), k=1,nk(m)), n=1,5)
      enddo

TECPLOT 的 PREPLOT 可以把 PLOT3D 文件转为 TECPLOT 格式。(没有测试)

20090526 add
由于后来发现可以用flow3d自带的命令行方式后处理提取数据,所以这个方法放弃。

一个简单的动态数据容器

能够动态的添加成员数据,目前只支持integer(4)和real(8)

 

! dynamic data type
! Qu Kun, April 2012
! 一个简单的动态数据结构容器,能够容纳INTEGER(4)和REAL(8)数据,维数范围为0到5
! 多个容器可链接成为链表
! 在链表中创建插入容器 dyd_new,指定数据类型、维数、指标范围和名称
! 获取容器指针 dyd_findnode 在链表中搜索指定名称的容器
! 释放容器内的数据空间 dyd_empty
! 开辟容器数据空间 dyd_construct
! 获取数据指针 dyd_getdata, 通过名称得到数据指针
!  
! 一般使用最常用的是 dyd_new和dyd_getdata
! dyd_new的使用方法,建议采用关键字方式指定参数
! 1 变量指定数组范围,range11,range12,range21,range22,...,range51,range52
!   CALL dyd_new(head=list, elementtype='integer(4)', dataname='X', ierr=ierr, &
!        range11=0,range12=9)
! 2 字符串指定数组范围
!   CALL dyd_new(head=list, elementtype='integer(4)', arrayrange='(0:9)',   &
!       dataname='X', ierr=ierr)
! 3 数组方式指定数组范围
! CALL dyd_new(head=list, atype=int4, adim=1,arange=irange, aname='X')
! 比较方便的是前2种
!
! 获取数据指针的方法为
! INTEGER(4),DIMENSION(:),POINTER :: X
! ...
! CALL getdata(list,'X', X)
! DO i=0,9;  X(i) = i; ENDDO


MODULE qkdynadata
IMPLICIT NONE
INTEGER,PARAMETER,PRIVATE :: dyd_maxdim=5,dyd_namelen=32
INTEGER,PARAMETER,PRIVATE :: int4=1,real8=2
TYPE dynadata
  INTEGER :: mdim=-1
  INTEGER :: mrange(2,dyd_maxdim)=-1
  INTEGER :: metype=-1  ! data type of the element, integer(4), real(8),real(4)
  CHARACTER(LEN=dyd_namelen) mname
 
  INTEGER(4),POINTER :: mint4d0p=>NULL()
  INTEGER(4),POINTER,DIMENSION(:) :: mint4d1p=>NULL()
  INTEGER(4),POINTER,DIMENSION(:,:) :: mint4d2p=>NULL()
  INTEGER(4),POINTER,DIMENSION(:,:,:) :: mint4d3p=>NULL()
  INTEGER(4),POINTER,DIMENSION(:,:,:,:) :: mint4d4p=>NULL()
  INTEGER(4),POINTER,DIMENSION(:,:,:,:,:) :: mint4d5p=>NULL()
 
  REAL(8),POINTER :: mreal8d0p=>NULL()
  REAL(8),POINTER,DIMENSION(:) :: mreal8d1p=>NULL()
  REAL(8),POINTER,DIMENSION(:,:) :: mreal8d2p=>NULL()
  REAL(8),POINTER,DIMENSION(:,:,:) :: mreal8d3p=>NULL()
  REAL(8),POINTER,DIMENSION(:,:,:,:) :: mreal8d4p=>NULL()
  REAL(8),POINTER,DIMENSION(:,:,:,:,:) :: mreal8d5p=>NULL()
 
  !pointer for inner dynamic data member
  TYPE(dynadata),POINTER :: mdynadata
 
  ! pointer for linklist
  TYPE(dynadata),POINTER :: mprev,mnext,mhead
 
END TYPE
 
 
INTERFACE getdata
  MODULE PROCEDURE getdata_int4p0
  MODULE PROCEDURE getdata_int4p1
  MODULE PROCEDURE getdata_int4p2
  MODULE PROCEDURE getdata_int4p3
  MODULE PROCEDURE getdata_int4p4
  MODULE PROCEDURE getdata_int4p5
  MODULE PROCEDURE getdata_real8p0
  MODULE PROCEDURE getdata_real8p1
  MODULE PROCEDURE getdata_real8p2
  MODULE PROCEDURE getdata_real8p3
  MODULE PROCEDURE getdata_real8p4
  MODULE PROCEDURE getdata_real8p5
END INTERFACE
 
CONTAINS
 
SUBROUTINE getdata_int4p0(head,aname, dp)
  INTEGER(4),POINTER :: dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  IF(ASSOCIATED(iter)) dp => iter%mint4d0p
END SUBROUTINE
 
SUBROUTINE getdata_int4p1(head,aname,dp)
  INTEGER(4),DIMENSION(:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
 ! WRITE(*,*) iter%mname
  dp => iter%mint4d1p
END SUBROUTINE
 
SUBROUTINE getdata_int4p2(head,aname,dp)
  INTEGER(4),DIMENSION(:,:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mint4d2p
END SUBROUTINE
 
 
SUBROUTINE getdata_int4p3(head,aname,dp)
  INTEGER(4),DIMENSION(:,:,:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mint4d3p
END SUBROUTINE
 
 
SUBROUTINE getdata_int4p4(head,aname,dp)
  INTEGER(4),DIMENSION(:,:,:,:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mint4d4p
END SUBROUTINE
 
 
SUBROUTINE getdata_int4p5(head,aname,dp)
  INTEGER(4),DIMENSION(:,:,:,:,:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mint4d5p
END SUBROUTINE
 
 
 
 
 
 
 
SUBROUTINE getdata_real8p0(head,aname, dp)
  REAL(8),POINTER :: dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mreal8d0p
END SUBROUTINE
 
SUBROUTINE getdata_real8p1(head,aname,dp)
  REAL(8),DIMENSION(:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mreal8d1p
END SUBROUTINE
 
SUBROUTINE getdata_real8p2(head,aname,dp)
  REAL(8),DIMENSION(:,:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mreal8d2p
END SUBROUTINE
 
 
SUBROUTINE getdata_real8p3(head,aname,dp)
  REAL(8),DIMENSION(:,:,:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mreal8d3p
END SUBROUTINE
 
 
SUBROUTINE getdata_real8p4(head,aname,dp)
  REAL(8),DIMENSION(:,:,:,:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mreal8d4p
END SUBROUTINE
 
 
SUBROUTINE getdata_real8p5(head,aname,dp)
  REAL(8),DIMENSION(:,:,:,:,:),POINTER ::dp
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
  NULLIFY(dp)
  iter => dyd_findnode(head,aname)
  dp => iter%mreal8d5p
END SUBROUTINE
 
 
 
 
SUBROUTINE dyd_empty(this)
  TYPE(dynadata),INTENT(INOUT) :: this
  ! local
  LOGICAL fk
  INTEGER ierr
  this%mdim=-1; this%mrange=-1; this%metype=-1; this%mname=''
 
  NULLIFY(this%mdynadata)
  NULLIFY(this%mprev)
  NULLIFY(this%mnext)
  NULLIFY(this%mhead)
  IF(ASSOCIATED(this%mint4d0p)) THEN
    DEALLOCATE(this%mint4d0p,STAT=ierr);    NULLIFY(this%mint4d0p)
  ENDIF 
   
 
  IF(ASSOCIATED(this%mint4d1p)) THEN
    DEALLOCATE(this%mint4d1p,STAT=ierr)
    NULLIFY(this%mint4d1p)
  ENDIF
 
  IF(ASSOCIATED(this%mint4d2p)) THEN
    DEALLOCATE(this%mint4d2p,STAT=ierr)
    NULLIFY(this%mint4d2p)
  ENDIF
   
  IF(ASSOCIATED(this%mint4d3p)) THEN
    DEALLOCATE(this%mint4d3p,STAT=ierr)
    NULLIFY(this%mint4d3p)
  ENDIF
  IF(ASSOCIATED(this%mint4d4p)) THEN
    DEALLOCATE(this%mint4d4p,STAT=ierr)
    NULLIFY(this%mint4d4p)
  ENDIF
   
  IF(ASSOCIATED(this%mint4d5p)) THEN
    DEALLOCATE(this%mint4d5p,STAT=ierr)
    NULLIFY(this%mint4d5p)
  ENDIF
 
  IF(ASSOCIATED(this%mreal8d0p)) THEN
    DEALLOCATE(this%mreal8d0p,STAT=ierr); NULLIFY(this%mreal8d0p)
  ENDIF
 
  IF(ASSOCIATED(this%mreal8d1p)) THEN
    DEALLOCATE(this%mreal8d1p,STAT=ierr); NULLIFY(this%mreal8d1p)
  ENDIF
   
  IF(ASSOCIATED(this%mreal8d2p)) THEN
    DEALLOCATE(this%mreal8d2p,STAT=ierr); NULLIFY(this%mreal8d2p)
  ENDIF
   
  IF(ASSOCIATED(this%mreal8d3p)) THEN
    DEALLOCATE(this%mreal8d3p,STAT=ierr); NULLIFY(this%mreal8d3p)
  ENDIF
   
  IF(ASSOCIATED(this%mreal8d4p)) THEN
    DEALLOCATE(this%mreal8d4p,STAT=ierr); NULLIFY(this%mreal8d4p)
  ENDIF
  IF(ASSOCIATED(this%mreal8d5p)) THEN
    DEALLOCATE(this%mreal8d5p,STAT=ierr); NULLIFY(this%mreal8d5p)
  ENDIF
 
END SUBROUTINE
 
 
 
 
 
SUBROUTINE dyd_new(head,elementtype, dataname, ierr,  &
          range11, range12,range21, range22,range31, range32, &
          range41, range42,range51, range52)
  TYPE(dynadata),POINTER,INTENT(INOUT) :: head
  CHARACTER(LEN=*),INTENT(IN) :: elementtype, dataname
  INTEGER,INTENT(IN),OPTIONAL :: range11, range12,range21, range22,  &
          range31, range32, range41, range42,range51, range52
  INTEGER,INTENT(OUT) :: ierr
  ! local
  INTEGER :: atype,adim
  INTEGER :: arange(2,10)
  TYPE(dynadata),POINTER :: pdyd
  CHARACTER(LEN=32) :: tstr
  
  ierr=0
  
  IF(.NOT.dyd_isvalidname(head,dataname)) THEN
   ierr=1
   RETURN
  ENDIF
  
  ! get type
  tstr = TRIM(elementtype)
  CALL  upper_case(tstr)
  IF(tstr=='INTEGER(4)') THEN;    atype=int4
  ELSEIF(tstr=='REAL(8)') THEN;   atype=real8
  ELSE
    ierr=2
    RETURN
  ENDIF
  
  ! get
  adim=0
  IF( PRESENT(range11) .AND. PRESENT(range12) ) THEN
    IF(range11>=range12) THEN
      WRITE(*,*) 'Invalid range'; ierr=3
      RETURN
    ENDIF
    adim=1; arange(1,1)=range11; arange(2,1)=range12
    ! DIM 2
    IF( PRESENT(range21) .AND. PRESENT(range22) ) THEN
      IF(range21>=range22) THEN
        WRITE(*,*) 'Invalid range'; ierr=3
      RETURN
      ENDIF
      adim=2; arange(1,2)=range21; arange(2,2)=range22
      ! DIM 3
      IF( PRESENT(range31) .AND. PRESENT(range32) ) THEN
        IF(range31>=range32) THEN
          WRITE(*,*) 'Invalid range'; ierr=3
          RETURN
        ENDIF
        adim=3; arange(1,3)=range31; arange(2,3)=range32
        ! DIM 4
        IF( PRESENT(range41) .AND. PRESENT(range42) ) THEN
          IF(range41>=range42) THEN
            WRITE(*,*) 'Invalid range'; ierr=3
            RETURN
          ENDIF
          adim=4; arange(1,4)=range41; arange(2,4)=range42
          ! DIM 5
          IF( PRESENT(range51) .AND. PRESENT(range52) ) THEN
            IF(range51>=range52) THEN
              WRITE(*,*) 'Invalid range'; ierr=3
              RETURN
            ENDIF
            adim=5; arange(1,5)=range51; arange(2,5)=range52
            ENDIF
          ENDIF
      ENDIF
    ENDIF
  ENDIF
 
  !WRITE(*,*) 'dyd_new ',atype,adim,arange(:,1:adim),dataname 
  CALL dyd_new_0(head,atype,adim,arange,dataname)
END SUBROUTINE
 
 
 
 
SUBROUTINE dyd_new_1(head,elementtype, arrayrange, dataname, ierr)
  TYPE(dynadata),POINTER,INTENT(INOUT) :: head
  CHARACTER(LEN=*),INTENT(IN) :: elementtype, arrayrange,dataname
  INTEGER,INTENT(OUT) :: ierr
  ! local
  INTEGER :: atype,offset,suboffset,i,adim
  INTEGER :: arange(2,10), loc(20),com(10)
  TYPE(dynadata),POINTER :: pdyd
  CHARACTER(LEN=32) :: tstr

  !WRITE(*,*) 'new1 ',dataname
 
  ierr=0
  
  IF(.NOT.dyd_isvalidname(head,dataname)) THEN
   ierr=1
   RETURN
  ENDIF
  
  ! get type
  tstr = TRIM(elementtype)
  CALL  upper_case(tstr)
  IF(tstr=='INTEGER(4)') THEN;    atype=int4
  ELSEIF(tstr=='REAL(8)') THEN;   atype=real8
  ELSE
    ierr=2
    RETURN
  ENDIF
  
  ! get
  adim=0; offset=1
  DO
    suboffset = INDEX(arrayrange(offset:),':')
    IF(suboffset==0) EXIT
    adim = adim+1
    IF(adim>5) STOP
    offset = offset+suboffset
  ENDDO
  !WRITE(*,*) 'adim=',adim,'   ',arrayrange
  
  IF(adim>0) THEN
      loc(1) = INDEX(arrayrange,'(')
      loc(adim+1) = INDEX(arrayrange,')')
      com(1) = INDEX(arrayrange,':')
      IF(adim>1) THEN
      DO i=2,adim
        loc(i) = loc(i-1)+INDEX(arrayrange(loc(i-1)+1:),',')
        !write(*,*) loc(i),'   ',arrayrange(loc(i-1)+1:)
        com(i) = loc(i)+INDEX(arrayrange(loc(i)+1:),':')
        !write(*,*) com(i),'   ',arrayrange(loc(i)+1:)
      ENDDO
      ENDIF
      write(*,*) loc(1:adim+1)
      write(*,*) com(1:adim)
      DO i=1,adim
        READ( arrayrange(loc(i)+1 : com(i)-1  ),  *)  arange(1,i)
        READ( arrayrange(com(i)+1 : loc(i+1)-1),  *)  arange(2,i)
      ENDDO
  ENDIF
  
  CALL dyd_new_0(head,atype,adim,arange,dataname)
  !NULLIFY(pdyd)
  !ALLOCATE(pdyd)
  !CALL dyd_construct(pdyd, atype,adim,arange,dataname)
  !CALL dyd_insert(pdyd,head)
END SUBROUTINE
 
 
SUBROUTINE dyd_new_0(head,atype,adim,arange,aname)
  TYPE(dynadata),POINTER,INTENT(INOUT) :: head
  INTEGER,INTENT(IN) :: atype,adim
  INTEGER,INTENT(IN),OPTIONAL :: arange(2,adim)
  CHARACTER(LEN=*),INTENT(IN) :: aname
  ! local
  TYPE(dynadata),POINTER :: pdyd

 
  NULLIFY(pdyd)
  IF(dyd_isvalidname(head,aname)) THEN
    ALLOCATE(pdyd)
    CALL dyd_construct(pdyd, atype,adim,arange,aname)
    CALL dyd_insert(pdyd,head)
  ENDIF
END SUBROUTINE
 
 
 
 
SUBROUTINE dyd_construct(this,atype,adim,arange,aname)
  TYPE(dynadata),INTENT(INOUT) :: this
  INTEGER,INTENT(IN) :: atype,adim
  INTEGER,INTENT(IN),OPTIONAL :: arange(2,adim)
  CHARACTER(LEN=*),INTENT(IN) :: aname
  !
  INTEGER i
 
  CALL dyd_empty(this)
  IF(atype<=0 .OR. atype>2) THEN
    WRITE(*,*) 'Invalid type: ',atype
    STOP
  ENDIF
 
  IF(adim<0) THEN
    WRITE(*,*) 'Invalid dim: ',adim
    STOP
  ENDIF
 
  IF(adim>0) THEN;  DO i=1,adim
    IF(arange(1,i)>arange(2,i)) THEN
      WRITE(*,*) 'Invalid range: ',arange(1:2,i), ' in DIM ',i
      STOP
    ENDIF
  ENDDO;  ENDIF
 
  this%mname = aname
  this%metype=atype
  this%mdim=adim
  IF(adim>0) this%mrange(1:2,1:adim) = arange(1:2,1:adim)
 
  SELECT CASE(this%metype)
    CASE (int4)
       IF(this%mdim==0) THEN
         ALLOCATE(this%mint4d0p)
       ENDIF
       IF(this%mdim==1) THEN
         ALLOCATE(this%mint4d1p(this%mrange(1,1):this%mrange(2,1) ) )
       ENDIF
       IF(this%mdim==2) THEN
         ALLOCATE(this%mint4d2p(this%mrange(1,1):this%mrange(2,1), &
                                this%mrange(1,2):this%mrange(2,2) ) )
       ENDIF
       IF(this%mdim==3) THEN
         ALLOCATE(this%mint4d3p(this%mrange(1,1):this%mrange(2,1), &
                                this%mrange(1,2):this%mrange(2,2), &
                                this%mrange(1,3):this%mrange(2,3) ) )
       ENDIF
       IF(this%mdim==4) THEN
         ALLOCATE(this%mint4d4p(this%mrange(1,1):this%mrange(2,1), &
                                this%mrange(1,2):this%mrange(2,2), &
                                this%mrange(1,3):this%mrange(2,3), &
                                this%mrange(1,4):this%mrange(2,4) ) )
       ENDIF
       IF(this%mdim==5) THEN
         ALLOCATE(this%mint4d5p(this%mrange(1,1):this%mrange(2,1), &
                                this%mrange(1,2):this%mrange(2,2), &
                                this%mrange(1,3):this%mrange(2,3), &
                                this%mrange(1,4):this%mrange(2,4), &
                                this%mrange(1,5):this%mrange(2,5) ) )
       ENDIF
    CASE (real8)
       IF(this%mdim==0) THEN
         ALLOCATE(this%mreal8d0p)
       ENDIF
       IF(this%mdim==1) THEN
         ALLOCATE(this%mreal8d1p(this%mrange(1,1):this%mrange(2,1) ) )
       ENDIF
       IF(this%mdim==2) THEN
         ALLOCATE(this%mreal8d2p(this%mrange(1,1):this%mrange(2,1), &
                                 this%mrange(1,2):this%mrange(2,2) ) )
       ENDIF
       IF(this%mdim==3) THEN
         ALLOCATE(this%mreal8d3p(this%mrange(1,1):this%mrange(2,1), &
                                 this%mrange(1,2):this%mrange(2,2), &
                                 this%mrange(1,3):this%mrange(2,3) ) )
       ENDIF
       IF(this%mdim==4) THEN
         ALLOCATE(this%mreal8d4p(this%mrange(1,1):this%mrange(2,1), &
                                 this%mrange(1,2):this%mrange(2,2), &
                                 this%mrange(1,3):this%mrange(2,3), &
                                 this%mrange(1,4):this%mrange(2,4) ) )
       ENDIF
       IF(this%mdim==5) THEN
         ALLOCATE(this%mreal8d5p(this%mrange(1,1):this%mrange(2,1), &
                                 this%mrange(1,2):this%mrange(2,2), &
                                 this%mrange(1,3):this%mrange(2,3), &
                                 this%mrange(1,4):this%mrange(2,4), &
                                 this%mrange(1,5):this%mrange(2,5) ) )
       ENDIF
  END SELECT
END SUBROUTINE
 
 
 
SUBROUTINE dyd_insert(this,head)
  TYPE(dynadata),POINTER,INTENT(INOUT) :: this
  TYPE(dynadata),POINTER,INTENT(INOUT) :: head
  !
  TYPE(dynadata),POINTER :: tail
  IF( ASSOCIATED(head) ) THEN
    CALL dyd_gettail(head,tail)
    !WRITE(*,*) 'Tail name is ',TRIM(tail%mname)
    this%mprev => tail
    this%mhead => head
    tail%mnext => this
    NULLIFY(this%mnext)
  ELSE
    head => this
    this%mprev => NULL()
    this%mhead => this
    this%mnext => NULL()
  ENDIF
END SUBROUTINE
 
SUBROUTINE dyd_gettail(this,tail)
  TYPE(dynadata),POINTER,INTENT(IN) :: this
  TYPE(dynadata),POINTER,INTENT(OUT) :: tail
 
  IF(ASSOCIATED(this)) THEN
    tail => this
    DO WHILE( ASSOCIATED(tail%mnext) )
      tail => tail%mnext
    END DO
  ENDIF
 
END SUBROUTINE
 
 
FUNCTION  dyd_isvalidname(head,aname)
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  LOGICAL dyd_isvalidname
  !
  TYPE(dynadata),POINTER :: iter
 
  dyd_isvalidname = .TRUE.
  IF( ASSOCIATED(head) ) THEN
    iter=>head
    DO WHILE( ASSOCIATED(iter%mnext) )
    !WRITE(*,*) TRIM(aname), '  ',TRIM(iter%mname)
    !READ(*,*)
    IF(TRIM(aname)==TRIM(iter%mname)) THEN
      dyd_isvalidname = .FALSE.
      EXIT
    ENDIF
    iter => iter%mnext
    END DO
  ENDIF
END FUNCTIOn
 
FUNCTION dyd_findnode(head,aname)
  TYPE(dynadata),POINTER,INTENT(IN) :: head
  CHARACTER(LEN=*),INTENT(IN) :: aname
  TYPE(dynadata),POINTER :: dyd_findnode
  !
  TYPE(dynadata),POINTER :: iter=>NULL()
 
  NULLIFY(dyd_findnode)
  IF(.NOT.ASSOCIATED(head)) RETURN
  iter=>head
  loop: DO
    IF(TRIM(aname)==TRIM(iter%mname)) THEN
      dyd_findnode => iter   ! 找到
      EXIT loop
    ENDIF
    IF(.NOT.ASSOCIATED(iter%mnext)) THEN
      EXIT loop              ! 队列结束,没找到
    ELSE
      iter=>iter%mnext
    ENDIF
  END DO loop
   
END FUNCTION
 
 
 
 
! other
elemental subroutine upper_case(word)
! convert a word to lower case
character (len=*) , intent(in out) :: word
integer :: i,ic,nlen
nlen = len(word)
do i=1,nlen
   ic = ichar(word(i:i))
   if (ic >= 97 .and. ic < 122) word(i:i) = char(ic-32)
end do
end subroutine upper_case


 
END MODULE
 
 

 

测试代码如下

 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
 
SUBROUTINE TEST_int4d0
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  INTEGER(4),POINTER :: X
  INTEGER ::ierr
 
   
  !CALL dyd_new(head=list, atype=int4, adim=1,arange=irange, aname='X')
  !CALL dyd_new(head=list, elementtype='integer(4)', arrayrange='(0:9)',   &
  !     dataname='X', ierr=ierr)
  CALL dyd_new(head=list, elementtype='integer(4)', dataname='X', ierr=ierr)
  CALL getdata(list,'X', X)
 
  iter => dyd_findnode(head=list,aname='X'); !X => iter%mint4d1p
  WRITE(*,*) X
  X = 5
  WRITE(*,*)iter%mint4d0p
 
  CALL dyd_empty(iter)
END  SUBROUTINE
 
 
SUBROUTINE TEST_int4d1
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  INTEGER(4),DIMENSION(:),POINTER :: X
  INTEGER ::i, irange(2,2),ierr
  irange(1,1) =0; irange(2,1) =9
   
  !CALL dyd_new(head=list, atype=int4, adim=1,arange=irange, aname='X')
  !CALL dyd_new(head=list, elementtype='integer(4)', arrayrange='(0:9)',   &
  !     dataname='X', ierr=ierr)
  CALL dyd_new(head=list, elementtype='integer(4)', dataname='X', ierr=ierr, &
       range11=0,range12=9)
  CALL getdata(list,'X', X)
 
  iter => dyd_findnode(head=list,aname='X'); !X => iter%mint4d1p
  WRITE(*,*) X
  WRITE(*,*) SHAPE(X),LBOUND(X),UBOUND(X)
  X = 5
  DO i=0,9;  X(i) = i; ENDDO
  WRITE(*,*)iter%mint4d1p
 
  CALL dyd_empty(iter)
END  SUBROUTINE


SUBROUTINE TEST_int4d2
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  INTEGER(4),DIMENSION(:,:),POINTER :: X
  INTEGER ::i,j,k, irange(2,2),ierr
  irange(1,1) =0; irange(2,1) =9
  irange(1,2) =1; irange(2,2) =5
  !CALL dyd_new(head=list, atype=int4, adim=1,arange=irange, aname='X')
  !CALL dyd_new(head=list, elementtype='integer(4)', arrayrange='(0:9)',   &
  !     dataname='X', ierr=ierr)
  CALL dyd_new(head=list, elementtype='integer(4)', dataname='X', ierr=ierr, &
       range11=0,range12=9,range21=1,range22=5)
  CALL getdata(list,'X', X)

  iter => dyd_findnode(head=list,aname='X'); !X => iter%mint4d1p
  WRITE(*,*) X
  WRITE(*,*) 'SHAPE(X)=',SHAPE(X),'LBOUND(X)=',LBOUND(X),'UBOUND(X)=',UBOUND(X)
  k=1
  DO j=1,5;DO i=0,9; X(i,j) = k; k=k+1; ENDDO;ENDDO
  WRITE(*,*)iter%mint4d2p

  CALL dyd_empty(iter)
END  SUBROUTINE
 

SUBROUTINE TEST_int4d3
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  INTEGER(4),DIMENSION(:,:,:),POINTER :: X
  INTEGER ::i,j,k,l,m,n, irange(2,3),ierr
  irange(1,1) =0; irange(2,1) =9
  irange(1,2) =1; irange(2,2) =5
  irange(1,3) =1; irange(2,3) =3
  !CALL dyd_new(head=list, atype=int4, adim=3,arange=irange, aname='X')
  CALL dyd_new(head=list, elementtype='integer(4)', arrayrange='(0:9,1:5,1:3)',   &
       dataname='X', ierr=ierr)
  !CALL dyd_new(head=list, elementtype='integer(4)', dataname='X', ierr=ierr, &
  !     range11=0,range12=9,range21=1,range22=5,range31=1,range32=3)
  CALL getdata(list,'X', X)

  iter => dyd_findnode(head=list,aname='X'); !X => iter%mint4d1p
  WRITE(*,*) X
  WRITE(*,*) 'SHAPE(X)=',SHAPE(X),'LBOUND(X)=',LBOUND(X),'UBOUND(X)=',UBOUND(X)
  k=1
  DO l=1,3; DO j=1,5;DO i=0,9
    X(i,j,l) = k; k=k+1
  ENDDO;ENDDO;ENDDO
  WRITE(*,*)iter%mint4d3p

  CALL dyd_empty(iter)
END  SUBROUTINE



SUBROUTINE TEST_int4d4
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  INTEGER(4),DIMENSION(:,:,:,:),POINTER :: X
  INTEGER ::i,j,k,l,m,n, irange(2,4),ierr
  irange(1,1) =0; irange(2,1) =2
  irange(1,2) =1; irange(2,2) =5
  irange(1,3) =1; irange(2,3) =3
  irange(1,4) =-1; irange(2,4) =1
  CALL dyd_new(head=list, atype=int4, adim=4,arange=irange, aname='X')
  !CALL dyd_new(head=list, elementtype='integer(4)', arrayrange='(0:9,1:5,1:3)',   &
  !     dataname='X', ierr=ierr)
  !CALL dyd_new(head=list, elementtype='integer(4)', dataname='X', ierr=ierr, &
  !     range11=0,range12=9,range21=1,range22=5,range31=1,range32=3)
  CALL getdata(list,'X', X)

  iter => dyd_findnode(head=list,aname='X'); !X => iter%mint4d1p
  WRITE(*,*) X
  WRITE(*,*) 'SHAPE(X)=',SHAPE(X),'LBOUND(X)=',LBOUND(X),'UBOUND(X)=',UBOUND(X)
  k=1
  DO m=irange(1,4), irange(2,4)
  DO l=irange(1,3), irange(2,3)
  DO j=irange(1,2), irange(2,2)
  DO i=irange(1,1), irange(2,1)
    X(i,j,l,m) = k; k=k+1
  ENDDO;ENDDO;ENDDO;ENDDO
  WRITE(*,*)iter%mint4d4p

  CALL dyd_empty(iter)
END  SUBROUTINE


SUBROUTINE TEST_int4d5
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  INTEGER(4),DIMENSION(:,:,:,:,:),POINTER :: X
  INTEGER ::i,j,k,l,m,n, irange(2,5),ierr
  irange(1,1) =0; irange(2,1) =2
  irange(1,2) =1; irange(2,2) =5
  irange(1,3) =1; irange(2,3) =3
  irange(1,4) =-1; irange(2,4) =1
  irange(1,5) =5; irange(2,5) =8
  !CALL dyd_new(head=list, atype=int4, adim=5,arange=irange, aname='X')
  CALL dyd_new(head=list, elementtype='integer(4)', arrayrange='(0:2,1:5,1:3,-1:1,5:8)',   &
       dataname='X', ierr=ierr)
  !CALL dyd_new(head=list, elementtype='integer(4)', dataname='X', ierr=ierr, &
  !     range11=0,range12=9,range21=1,range22=5,range31=1,range32=3)
  CALL getdata(list,'X', X)

  iter => dyd_findnode(head=list,aname='X'); !X => iter%mint4d1p
  !WRITE(*,*) X
  WRITE(*,*) 'SHAPE(X)=',SHAPE(X),'LBOUND(X)=',LBOUND(X),'UBOUND(X)=',UBOUND(X)
  k=1
  DO n=irange(1,5), irange(2,5)
  DO m=irange(1,4), irange(2,4)
  DO l=irange(1,3), irange(2,3)
  DO j=irange(1,2), irange(2,2)
  DO i=irange(1,1), irange(2,1)
    X(i,j,l,m,n) = k; k=k+1
  ENDDO;ENDDO;ENDDO;ENDDO;ENDDO
  WRITE(*,*)iter%mint4d5p

  CALL dyd_empty(iter)
END  SUBROUTINE


SUBROUTINE TEST_real8d0
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  REAL(8),POINTER :: X
  INTEGER ::ierr
 
   
  !CALL dyd_new(head=list, atype=real8, adim=1,arange=irange, aname='X')
  !CALL dyd_new(head=list, elementtype='REAL(8)', arrayrange='(0:9)',   &
  !     dataname='X', ierr=ierr)
  CALL dyd_new(head=list, elementtype='REAL(8)', dataname='X', ierr=ierr)
  CALL getdata(list,'X', X)
 
  iter => dyd_findnode(head=list,aname='X'); !X => iter%mreal8d1p
  !WRITE(*,*) X
  X = 5
  WRITE(*,*)iter%mreal8d0p
 
  CALL dyd_empty(iter)
END  SUBROUTINE
 
 
SUBROUTINE TEST_real8d1
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  REAL(8),DIMENSION(:),POINTER :: X
  INTEGER ::i, irange(2,2),ierr
  irange(1,1) =0; irange(2,1) =9
   
  !CALL dyd_new(head=list, atype=real8, adim=1,arange=irange, aname='X')
  !CALL dyd_new(head=list, elementtype='REAL(8)', arrayrange='(0:9)',   &
  !     dataname='X', ierr=ierr)
  CALL dyd_new(head=list, elementtype='REAL(8)', dataname='X', ierr=ierr, &
       range11=0,range12=9)
  CALL getdata(list,'X', X)
 
  iter => dyd_findnode(head=list,aname='X'); !X => iter%mreal8d1p
  !WRITE(*,*) X
  WRITE(*,*) SHAPE(X),LBOUND(X),UBOUND(X)
  X = 5
  DO i=0,9;  X(i) = i; ENDDO
  WRITE(*,*)iter%mreal8d1p
 
  CALL dyd_empty(iter)
END  SUBROUTINE


SUBROUTINE TEST_real8d2
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  REAL(8),DIMENSION(:,:),POINTER :: X
  INTEGER ::i,j,k, irange(2,2),ierr
  irange(1,1) =0; irange(2,1) =9
  irange(1,2) =1; irange(2,2) =5
  !CALL dyd_new(head=list, atype=real8, adim=1,arange=irange, aname='X')
  !CALL dyd_new(head=list, elementtype='REAL(8)', arrayrange='(0:9)',   &
  !     dataname='X', ierr=ierr)
  CALL dyd_new(head=list, elementtype='REAL(8)', dataname='X', ierr=ierr, &
       range11=0,range12=9,range21=1,range22=5)
  CALL getdata(list,'X', X)

  iter => dyd_findnode(head=list,aname='X'); !X => iter%mreal8d1p
  !WRITE(*,*) X
  WRITE(*,*) 'SHAPE(X)=',SHAPE(X),'LBOUND(X)=',LBOUND(X),'UBOUND(X)=',UBOUND(X)
  k=1
  DO j=1,5;DO i=0,9; X(i,j) = k; k=k+1; ENDDO;ENDDO
  WRITE(*,*)iter%mreal8d2p

  CALL dyd_empty(iter)
END  SUBROUTINE
 

SUBROUTINE TEST_real8d3
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  REAL(8),DIMENSION(:,:,:),POINTER :: X
  INTEGER ::i,j,k,l,m,n, irange(2,3),ierr
  irange(1,1) =0; irange(2,1) =9
  irange(1,2) =1; irange(2,2) =5
  irange(1,3) =1; irange(2,3) =3
  !CALL dyd_new(head=list, atype=real8, adim=3,arange=irange, aname='X')
  CALL dyd_new(head=list, elementtype='REAL(8)', arrayrange='(0:9,1:5,1:3)',   &
       dataname='X', ierr=ierr)
  !CALL dyd_new(head=list, elementtype='REAL(8)', dataname='X', ierr=ierr, &
  !     range11=0,range12=9,range21=1,range22=5,range31=1,range32=3)
  CALL getdata(list,'X', X)

  iter => dyd_findnode(head=list,aname='X'); !X => iter%mreal8d1p
  !WRITE(*,*) X
  WRITE(*,*) 'SHAPE(X)=',SHAPE(X),'LBOUND(X)=',LBOUND(X),'UBOUND(X)=',UBOUND(X)
  k=1
  DO l=1,3; DO j=1,5;DO i=0,9
    X(i,j,l) = k; k=k+1
  ENDDO;ENDDO;ENDDO
  WRITE(*,*)iter%mreal8d3p

  CALL dyd_empty(iter)
END  SUBROUTINE



SUBROUTINE TEST_real8d4
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  REAL(8),DIMENSION(:,:,:,:),POINTER :: X
  INTEGER ::i,j,k,l,m,n, irange(2,4),ierr
  irange(1,1) =0; irange(2,1) =2
  irange(1,2) =1; irange(2,2) =5
  irange(1,3) =1; irange(2,3) =3
  irange(1,4) =-1; irange(2,4) =1
  CALL dyd_new(head=list, atype=real8, adim=4,arange=irange, aname='X')
  !CALL dyd_new(head=list, elementtype='REAL(8)', arrayrange='(0:9,1:5,1:3)',   &
  !     dataname='X', ierr=ierr)
  !CALL dyd_new(head=list, elementtype='REAL(8)', dataname='X', ierr=ierr, &
  !     range11=0,range12=9,range21=1,range22=5,range31=1,range32=3)
  CALL getdata(list,'X', X)

  iter => dyd_findnode(head=list,aname='X'); !X => iter%mreal8d1p
  !WRITE(*,*) X
  WRITE(*,*) 'SHAPE(X)=',SHAPE(X),'LBOUND(X)=',LBOUND(X),'UBOUND(X)=',UBOUND(X)
  k=1
  DO m=irange(1,4), irange(2,4)
  DO l=irange(1,3), irange(2,3)
  DO j=irange(1,2), irange(2,2)
  DO i=irange(1,1), irange(2,1)
    X(i,j,l,m) = k; k=k+1
  ENDDO;ENDDO;ENDDO;ENDDO
  WRITE(*,*)iter%mreal8d4p

  CALL dyd_empty(iter)
END  SUBROUTINE


SUBROUTINE TEST_real8d5
  USE xx
  IMPLICIT NONE
  TYPE(dynadata),POINTER :: list=>NULL(),iter=>NULL()
  REAL(8),DIMENSION(:,:,:,:,:),POINTER :: X
  INTEGER ::i,j,k,l,m,n, irange(2,5),ierr
  irange(1,1) =0; irange(2,1) =2
  irange(1,2) =1; irange(2,2) =5
  irange(1,3) =1; irange(2,3) =3
  irange(1,4) =-1; irange(2,4) =1
  irange(1,5) =5; irange(2,5) =8
  !CALL dyd_new(head=list, atype=real8, adim=5,arange=irange, aname='X')
  CALL dyd_new(head=list, elementtype='REAL(8)', arrayrange='(0:2,1:5,1:3,-1:1,5:8)',   &
       dataname='X', ierr=ierr)
  !CALL dyd_new(head=list, elementtype='REAL(8)', dataname='X', ierr=ierr, &
  !     range11=0,range12=9,range21=1,range22=5,range31=1,range32=3)
  CALL getdata(list,'X', X)

  iter => dyd_findnode(head=list,aname='X'); !X => iter%mreal8d1p
  !WRITE(*,*) X
  WRITE(*,*) 'SHAPE(X)=',SHAPE(X),'LBOUND(X)=',LBOUND(X),'UBOUND(X)=',UBOUND(X)
  k=1
  DO n=irange(1,5), irange(2,5)
  DO m=irange(1,4), irange(2,4)
  DO l=irange(1,3), irange(2,3)
  DO j=irange(1,2), irange(2,2)
  DO i=irange(1,1), irange(2,1)
    X(i,j,l,m,n) = k; k=k+1
  ENDDO;ENDDO;ENDDO;ENDDO;ENDDO
  WRITE(*,*)iter%mreal8d5p

  CALL dyd_empty(iter)
  
  
  
  
END  SUBROUTINE

 
 
PROGRAM TEST
  IMPLICIT NONE
!  CALL TEST_int4d0
!  CALL TEST_int4d1
!  CALL TEST_int4d2
!  CALL TEST_int4d3
!  CALL TEST_int4d4
!  CALL TEST_int4d5

  CALL TEST_real8d0
  CALL TEST_real8d1
  CALL TEST_real8d2
  CALL TEST_real8d3
  CALL TEST_real8d4
  CALL TEST_real8d5
  
END

 

还好,fortran的指针还不算太差

指针可传给c语言做void*

program test
  implicit none
  integer,pointer,dimension(:,:) :: dat, ptr
  integer, target :: buff(10,10)
  integer(8) :: n,l,leng,buffsize

  leng = 100
  buffsize = leng*sizeof(buff(1,1))
  allocate(dat(1:10,1:10))
  leng = 1
  do n=1,10
  do l=1,10
   dat(l,n) = leng
   leng = leng + 1
  enddo
  enddo
  leng = 100
  ptr => dat 
  call cwrite(ptr, buffsize)
  ptr => buff
  call cread(ptr,buffsize)

  do n=1,10
   write(*,'(10I5)') buff(:,n)
  enddo


  deallocate(dat)
end

 

#include <stdio.h>

void cwrite_(void * buff, long int* len)
{
  long int i;
  FILE * fp;

  fp = fopen("test.dat","wb");
  fwrite(buff,1,*len,fp);
  fclose(fp);
}

void cread_(void * buff, long int* len)
{
  long int i;
  FILE * fp;

  fp = fopen("test.dat","rb");
  fread(buff,1,*len,fp);
  fclose(fp);
}

 




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee