• No results found

Supersonic turbulent combustion experiments

progam.f90

1 ! $Id: progam.f90,v 1.2 2006-07-16 23:07:26 emiliano Exp $ 2 ! PROGAM - Programa de Generación Automática de Mallas 3

4 PROGRAM progam_s 5 USE region_mod 6 IMPLICIT NONE 7

8 TYPE(region_t), ALLOCATABLE, TARGET :: regions(:)

9 INTEGER :: i, n_regions, nstart 10

11 ! Procesamiento de la entrada de datos 12 CALL region_input(regions)

13 n_regions = SIZE(regions) 14

15 ! Divide cada región en elementos cuadrangulares 16 DO i=1, n_regions

17 CALL region_grid(regions(i)) 18 END DO

19

20 ! Asigna un número único a cada nodo 21 nstart = 1

22 DO i=1, n_regions

23 CALL region_nodenums(regions(i), nstart, regions) 24 END DO

25

26 ! Genera los elementos 27 DO i=1, n_regions

28 CALL region_elements(regions(i)) 29 END DO

30

31 ! Salida para GiD

32 CALL region_output(regions) 33

34 END PROGRAM progam_s

region.f90

1 ! $Id: region.f90,v 1.2 2006-07-16 21:51:41 emiliano Exp $ 2 ! PROGAM - Programa de Generación Automática de Mallas 3 4 MODULE region_mod 5 !DEC$ REAL:8 6 IMPLICIT NONE 7 8 TYPE region_t

9 INTEGER :: num ! número de región

10 INTEGER :: n, m ! cantidad de filas y columnas 11 INTEGER :: elem_type ! 3=triángulo, 4=cuadrado 12 INTEGER :: vecinas(4) ! datos de conectividad

13 REAL :: def_nodes(8,2) ! los 8 nodos que definen la región 14 REAL, ALLOCATABLE :: node_coords(:,:,:) ! coordenadas de los nodos

15 INTEGER, ALLOCATABLE :: node_nums(:,:) ! números de los nodos

16 INTEGER, ALLOCATABLE :: elements(:,:) ! cada elemento es un vector de 3 o 4 enteros 17 END TYPE region_t

18

19 CONTAINS

20 ! Procesamiento de la entrada de datos 21 SUBROUTINE region_input(regions)

22 TYPE(region_t), TARGET, ALLOCATABLE, INTENT(OUT) :: regions(:) 23 REAL, ALLOCATABLE :: input_nodes(:,:)

26 INTEGER :: node_num, i 27

28 READ(*,*) n_regions, n_input_nodes

29 ALLOCATE(regions(n_regions), input_nodes(n_input_nodes,2)) 30

31 DO i=1, n_input_nodes

32 READ(*,*) node_num, input_nodes(i,:) 33 END DO 34 35 DO i=1, n_regions 36 READ(*,*) regions(i)%n,regions(i)%m,regions(i)%elem_type,regions(i)%vecinas,node_nums 37 regions(i)%num = i 38 regions(i)%def_nodes = input_nodes(node_nums,:) 39 END DO

40 END SUBROUTINE region_input 41

42 ! Divide la región en (n-1)*(m-1) elementos cuadrangulares. 43 SUBROUTINE region_grid(this)

44 TYPE(region_t), INTENT(INOUT) :: this 45 INTEGER :: i, j

46 REAL :: pun(8) ! funciones de forma 47 REAL :: eta, si ! coordenadas normalizadas 48 REAL :: deta, dsi ! incrementos de eta y si 49 50 ALLOCATE(this%node_coords(this%n,this%m,2)) 51 ALLOCATE(this%node_nums(this%n,this%m)) 52 53 deta = 2./(this%n-1) 54 dsi = 2./(this%m-1) 55 DO i=1, this%n 56 eta = 1 - (i-1)*deta 57 DO j=1, this%m 58 si = -1 + (j-1)*dsi

59 pun(1) = -0.25 * (1-si) * (1-eta) * (si+eta+1) 60 pun(2) = 0.5 * (1-si**2) * (1-eta)

61 pun(3) = 0.25 * (1+si) * (1-eta) * (si-eta-1) 62 pun(4) = 0.5 * (1+si) * (1-eta**2)

63 pun(5) = 0.25 * (1+si) * (1+eta) * (si+eta-1) 64 pun(6) = 0.5 * (1-si**2) * (1+eta)

65 pun(7) = 0.25 * (1-si) * (1+eta) * (eta-si-1) 66 pun(8) = 0.5 * (1-si) * (1 - eta**2)

67 this%node_coords(i,j,1) = SUM(this%def_nodes(:,1) * pun) 68 this%node_coords(i,j,2) = SUM(this%def_nodes(:,2) * pun) 69 END DO

70 END DO

71 END SUBROUTINE region_grid 72

73 ! Numera en forma global los nodos de la región, teniendo en cuenta los que 74 ! ya han sido numerados por otras regiones. La variable nstart contiene el 75 ! primer número de la secuencia, y devuelve el primer número de la siguiente 76 ! region.

77 SUBROUTINE region_nodenums(this, nstart, regions) 78 TYPE(region_t), TARGET, INTENT(INOUT) :: this 79 INTEGER, INTENT(INOUT) :: nstart 80 TYPE(region_t), INTENT(IN) :: regions(:)

81 INTEGER :: i, j, istart, jstart, iend, jend 82 INTEGER, POINTER :: bound_nums(:)

83 REAL :: chk_node(2), recv_node(2) 84 85 istart=1 86 jstart=1 87 iend=this%n 88 jend=this%m 89

90 ! Verifica si los nodos de las fronteras son numerados por otra región 91 IF (this%vecinas(1)<this%num .AND. this%vecinas(1)/=0) iend=iend-1 92 IF (this%vecinas(2)<this%num .AND. this%vecinas(2)/=0) jend=jend-1 93 IF (this%vecinas(3)<this%num .AND. this%vecinas(3)/=0) istart=istart+1 94 IF (this%vecinas(4)<this%num .AND. this%vecinas(4)/=0) jstart=jstart+1 95

96 ! Numera los nodos 97 DO i=istart, iend

98 DO j=jstart, jend 99 this%node_nums(i,j) = nstart 100 nstart = nstart+1 101 END DO 102 END DO 103

104 ! Numera las fronteras que no han sido numeradas 105 DO i=1, 4

106 SELECT CASE(i) 107 CASE(1)

108 bound_nums => this%node_nums(this%n,:) ! abajo 109 chk_node = this%node_coords(this%n,1,:)

110 CASE(2)

111 bound_nums => this%node_nums(:,this%m) ! derecha 112 chk_node = this%node_coords(1,this%m,:)

113 CASE(3)

114 bound_nums => this%node_nums(1,:) ! arriba 115 chk_node = this%node_coords(1,1,:)

116 CASE(4)

117 bound_nums => this%node_nums(:,1) ! izquierda 118 chk_node = this%node_coords(1,1,:)

119 END SELECT 120

121 IF (this%vecinas(i)<this%num .AND. this%vecinas(i)/=0) THEN

122 CALL region_bound(regions(this%vecinas(i)), this%num, bound_nums, recv_node) 123 IF (ANY(chk_node/=recv_node)) CALL invertir(bound_nums)

124 END IF 125 END DO

126 END SUBROUTINE region_nodenums 127

128 ! Devuelve los números de nodos que están en la frontera con una región específica. 129 SUBROUTINE region_bound(this, vecina, bound_nums, chk_node)

130 TYPE(region_t), INTENT(IN) :: this ! región origen 131 INTEGER, INTENT(IN) :: vecina ! región destino

132 INTEGER, INTENT(OUT) :: bound_nums(:) ! vector en el que se devuelven los números 133 REAL, INTENT(OUT) :: chk_node(2) ! coordenadas de uno de los extremos 134

135 ! No uso select case porque require expresiones constantes. 136 IF (vecina==this%vecinas(1)) THEN

137 bound_nums = this%node_nums(this%n,:) 138 chk_node = this%node_coords(this%n,1,:) 139 ELSE IF (vecina==this%vecinas(2)) THEN 140 bound_nums = this%node_nums(:,this%m) 141 chk_node = this%node_coords(1,this%m,:) 142 ELSE IF (vecina==this%vecinas(3)) THEN 143 bound_nums = this%node_nums(1,:) 144 chk_node = this%node_coords(1,1,:) 145 ELSE IF (vecina==this%vecinas(4)) THEN 146 bound_nums = this%node_nums(:,1) 147 chk_node = this%node_coords(1,1,:) 148 END IF

149 END SUBROUTINE region_bound 150

151 ! Invierte el orden de los elementos en el vector. 152 SUBROUTINE invertir(vector)

153 INTEGER, INTENT(INOUT) :: vector(:) 154 INTEGER :: aux(SIZE(vector)) 155 INTEGER :: i, n 156 157 n = SIZE(vector) 158 DO i=1, n 159 aux(n-i+1) = vector(i) 160 END DO 161 vector = aux

162 END SUBROUTINE invertir 163

164 ! Genera elementos triangulares (dividiendo los cuadrados según la diagonal más 165 ! corta del elemento (1,1)) o cuadrangulares. Cada elemento es un vector formado 166 ! por los números de los nodos que lo definen.

170 REAL :: diag1, diag2 171

172 IF (this%elem_type == 3) THEN ! elementos triangulares 173 ALLOCATE(this%elements((this%n-1)*(this%m-1)*2, 3)) 174 k = 1

175 diag1 = SQRT((this%node_coords(1,1,1)-this%node_coords(2,2,1))**2 & 176 + (this%node_coords(1,1,2)-this%node_coords(2,2,2))**2) 177 diag2 = SQRT((this%node_coords(2,1,1)-this%node_coords(1,2,1))**2 & 178 + (this%node_coords(2,1,2)-this%node_coords(1,2,2))**2) 179

180 IF (diag1 < diag2) THEN 181 DO i=1, this%n-1 182 DO j=1, this%m-1 183 this%elements(k,1) = this%node_nums(i,j) 184 this%elements(k,2) = this%node_nums(i+1,j) 185 this%elements(k,3) = this%node_nums(i+1,j+1) 186 k = k+1 187 this%elements(k,1) = this%node_nums(i,j) 188 this%elements(k,2) = this%node_nums(i+1,j+1) 189 this%elements(k,3) = this%node_nums(i,j+1) 190 k = k+1 191 END DO 192 END DO 193 ELSE 194 DO i=1, this%n-1 195 DO j=1, this%m-1 196 this%elements(k,1) = this%node_nums(i,j) 197 this%elements(k,2) = this%node_nums(i+1,j) 198 this%elements(k,3) = this%node_nums(i,j+1) 199 k = k+1 200 this%elements(k,1) = this%node_nums(i+1,j) 201 this%elements(k,2) = this%node_nums(i+1,j+1) 202 this%elements(k,3) = this%node_nums(i,j+1) 203 k = k+1 204 END DO 205 END DO 206 END IF 207

208 ELSE IF (this%elem_type == 4) THEN ! elementos cuadrangulares 209 ALLOCATE(this%elements((this%n-1)*(this%m-1), 4)) 210 k = 1 211 DO i=1, this%n-1 212 DO j=1, this%m-1 213 this%elements(k,1) = this%node_nums(i,j) 214 this%elements(k,2) = this%node_nums(i+1,j) 215 this%elements(k,3) = this%node_nums(i+1,j+1) 216 this%elements(k,4) = this%node_nums(i,j+1) 217 k = k+1 218 END DO 219 END DO 220 END IF

221 END SUBROUTINE region_elements 222

223 ! Salida para GiD

224 SUBROUTINE region_output(regions)

225 TYPE(region_t), INTENT(IN) :: regions(:)

226 INTEGER :: i, j, k, elem_num, node_num 227 228 elem_num = 1 229 node_num = 0 230 OPEN(UNIT=1, FILE='output.msh') 231 232 DO k=1, SIZE(regions) 233 ! Cabecera 234 IF (regions(k)%elem_type==3) THEN

235 WRITE(1,*) 'MESH dimension 2 ElemType Triangle Nnode 3' 236 ELSE IF (regions(k)%elem_type==4) THEN

237 WRITE(1,*) 'MESH dimension 2 ElemType Quadrilateral Nnode 4' 238 END IF

239

240 ! Coordenadas de los nodos 241 WRITE(1,*) 'coordinates'

242 WRITE(1,*) '# num x y' 243 DO i=1, regions(k)%n 244 DO j=1, regions(k)%m

245 IF (regions(k)%node_nums(i,j)>node_num) THEN 246 node_num = regions(k)%node_nums(i,j)

247 WRITE(1,*) node_num, regions(k)%node_coords(i,j,:) 248 END IF

249 END DO 250 END DO

251 WRITE(1,*) 'end coordinates' 252

253 ! Elementos

254 WRITE(1,*) 'elements'

255 WRITE(1,*) '# num nodo1 nodo2 nodo3 nodo4' 256 DO i=1, SIZE(regions(k)%elements, DIM=1) 257 WRITE(1,*) elem_num, regions(k)%elements(i,:) 258 elem_num = elem_num+1

259 END DO

260 WRITE(1,*) 'end elements' 261 WRITE(1,*)

262 END DO

263 END SUBROUTINE region_output 264 END MODULE region_mod

test.f90

1 ! $Id: test.f90,v 1.1.1.1 2006-07-16 21:18:46 emiliano Exp $ 2 ! PROGAM - Programa de Generación Automática de Mallas 3

4 ! Esta prueba genera sucesivamente mallas de elementos finitos, 5 ! aumentando la cantidad de elementos geométricamente. Para cada 6 ! malla se toma el tiempo de cálculo, sin considerar la entrada 7 ! ni la salida de datos. 8 9 PROGRAM progam_s_test 10 USE region_mod 11 IMPLICIT NONE 12

13 TYPE(region_t), ALLOCATABLE, TARGET :: regions(:)

14 INTEGER :: i, n_regions, nstart 15 REAL :: ti, tf

16 INTEGER :: ierr, k

17 INTEGER, ALLOCATABLE :: n_init(:), m_init(:) 18

19 ! Procesamiento de la entrada de datos 20 CALL region_input(regions) 21 n_regions = SIZE(regions) 22 23 ALLOCATE(n_init(n_regions), m_init(n_regions)) 24 n_init = regions%n 25 m_init = regions%m 26 27 DO k=1, 100 28 regions%n = n_init*k 29 regions%m = m_init*k 30 31 CALL CPU_TIME(ti)

32 ! Divide cada región en elementos cuadrangulares 33 DO i=1, n_regions

34 CALL region_grid(regions(i)) 35 END DO

36

37 ! Asigna un número único a cada nodo 38 nstart = 1

39 DO i=1, n_regions

40 CALL region_nodenums(regions(i), nstart, regions) 41 END DO

45 CALL region_elements(regions(i)) 46 END DO

47 CALL CPU_TIME(tf) 48

49 WRITE(*,*) DOT_PRODUCT(regions%n, regions%m), tf-ti 50 DO i=1, n_regions 51 DEALLOCATE(regions(i)%node_coords) 52 DEALLOCATE(regions(i)%node_nums) 53 DEALLOCATE(regions(i)%elements) 54 END DO 55 END DO 56