The TELEMAC-MASCARET system  trunk
topogr.f
Go to the documentation of this file.
1 ! *****************
2  SUBROUTINE topogr
3 ! *****************
4 !
5  &(zf,zref,zfe,ikle,ifabor,nbor,nelbor,nulone,
6  & itra05,itra02,itra03,nelem,nptfr,npoin,mxptvs)
7 !
8 !***********************************************************************
9 ! BIEF V6P1 21/08/2010
10 !***********************************************************************
11 !
12 !brief FINELY ANALYSES THE TOPOGRAPHY AND BUILDS ZFE.
13 !+
14 !+ THE ARRAY OF BOTTOM ELEVATIONS BY ELEMENTS: ZFE
15 !+ WILL ENSURE IN THE FUTURE THAT THERE WILL NOT BE
16 !+ LIQUID DOMAINS CONNECTED BY A SINGLE NODE.
17 !
18 !history J-M JANIN (LNH)
19 !+ 17/08/94
20 !+ V5P1
21 !+
22 !
23 !history N.DURAND (HRW), S.E.BOURBAN (HRW)
24 !+ 13/07/2010
25 !+ V6P0
26 !+ Translation of French comments within the FORTRAN sources into
27 !+ English comments
28 !
29 !history N.DURAND (HRW), S.E.BOURBAN (HRW)
30 !+ 21/08/2010
31 !+ V6P0
32 !+ Creation of DOXYGEN tags for automated documentation and
33 !+ cross-referencing of the FORTRAN sources
34 !
35 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
36 !| IFABOR |-->| ELEMENTS BEHIND THE EDGES OF A TRIANGLE
37 !| | | IF NEGATIVE OR ZERO, THE EDGE IS A LIQUID
38 !| | | BOUNDARY
39 !| IKLE |-->| CONNECTIVITY TABLE.
40 !| ITRA02 |<--| INTEGER WORK ARRAY
41 !| ITRA03 |<--| INTEGER WORK ARRAY
42 !| ITRA05 |<--| INTEGER WORK ARRAY
43 !| MXPTVS |-->| MAXIMUM NUMBER OF NEIGHBOURS OF A POINT
44 !| NBOR |-->| GLOBAL NUMBER OF BOUNDARY POINTS
45 !| NELBOR |-->| FOR THE KTH BOUNDARY EDGE, GIVES THE CORRESPONDING
46 !| | | ELEMENT.
47 !| NELEM |-->| NUMBER OF ELEMENTS
48 !| NPOIN |-->| NUMBER OF POINTS
49 !| NPTFR |-->| NUMBER OF BOUNDARY POINTS
50 !| NULONE |-->| GOES WITH ARRAY NELBOR. NELBOR GIVES THE
51 !| | | ADJACENT ELEMENT, NULONE GIVES THE LOCAL
52 !| | | NUMBER OF THE FIRST NODE OF THE BOUNDARY EDGE
53 !| | | I.E. 1, 2 OR 3 FOR TRIANGLES.
54 !| ZF |-->| ELEVATION OF BOTTOM, PER POINT
55 !| ZFE |<--| ELEVATION OF BOTTOM, PER ELEMENT
56 !| ZREF |<--| CORRECTED BOTTOM ELEVATION
57 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
58 !
60  IMPLICIT NONE
61 !
62 !+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 !
64  INTEGER, INTENT(IN) :: NELEM,NPTFR,NPOIN,MXPTVS
65  INTEGER, INTENT(IN) :: IKLE(nelem,3),IFABOR(nelem,3)
66  INTEGER, INTENT(IN) :: NBOR(nptfr),NELBOR(nptfr),NULONE(nptfr)
67  INTEGER, INTENT(INOUT) :: ITRA05(npoin),ITRA02(npoin)
68  INTEGER, INTENT(INOUT) :: ITRA03(npoin)
69  DOUBLE PRECISION, INTENT(INOUT) :: ZFE(nelem),ZREF(npoin)
70  DOUBLE PRECISION, INTENT(IN) :: ZF(npoin)
71 !
72 !+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 !
74  INTEGER IELEM,IPTFR,IPOIN,I,I1,I2,I3,N1,N2,ERR,IMAX
75  LOGICAL FLAG
76 !
77 ! DYNAMICALLY ALLOCATES INTEGERS
78 !
79  INTEGER, DIMENSION(:,:), ALLOCATABLE :: ITRA01,ITRA04,IFAN
80 !
81  INTEGER :: IPREV(3)
82  parameter( iprev = (/ 3 , 1 , 2 /) )
83  DOUBLE PRECISION, PARAMETER :: EPSILO = 1.d-6
84 !
85 !-----------------------------------------------------------------------
86 !
87  ALLOCATE(ifan(nelem,3) ,stat=err)
88  CALL check_allocate(err, 'IFAN')
89  ALLOCATE(itra01(npoin,mxptvs+1) ,stat=err)
90  CALL check_allocate(err, 'ITRA01')
91  ALLOCATE(itra04(npoin,6) ,stat=err)
92  CALL check_allocate(err, 'ITRA04')
93 !
94 !-----------------------------------------------------------------------
95 !
96 ! FILLS IN IFAN
97 !
98 ! IFAN(IELEM,IFACE) GIVES THE LOCAL NUMBER IN THE ELEMENT DEFINED
99 ! BY IFABOR(IELEM,IFACE) OF THE NODE WITH LOCAL NUMBER IFACE IN
100 ! ELEMENT IELEM.
101 !
102 ! FIRST GO AT FILLING ZFE
103 !
104 ! STARTS TO FILL IN ITRA01 AND ITRA02
105 !
106 ! ITRA01 AND ITRA02 PERFORM THE REVERSE OPERATION FROM IKLE.
107 ! IN THIS LOOP ITRA01(IPOIN,1) IS FILLED IN. IT GIVES THE BIGGEST
108 ! ELEMENT NUMBER CONTAINING IPOIN. ITRA02(IPOIN) GIVES THE LOCAL
109 ! NUMBER OF IPOIN IN THIS ELEMENT.
110 !
111 !-----------------------------------------------------------------------
112 !
113 ! INITIALISES ITRA01 TO DETECT HOLES IN THE MESH
114 ! (POINTS NOT LINKED TO AN ELEMENT, CASE OF CURVILINEAR MESH)
115 !
116  DO i1 = 1 , mxptvs+1
117  DO ipoin = 1 , npoin
118  itra01(ipoin,i1) = 0
119  ENDDO ! IPOIN
120  ENDDO ! I1
121 !
122 !
123  DO ielem = 1,nelem
124 !
125  i1 = ikle(ielem,1)
126  i2 = ikle(ielem,2)
127  i3 = ikle(ielem,3)
128 !
129  ifan(ielem,1) = 0
130  n1 = ifabor(ielem,1)
131  IF (n1.GT.0) THEN
132  IF(ikle(n1,1).EQ.i1) ifan(ielem,1) = 3
133  IF(ikle(n1,2).EQ.i1) ifan(ielem,1) = 1
134  IF(ikle(n1,3).EQ.i1) ifan(ielem,1) = 2
135  ENDIF
136 !
137  ifan(ielem,2) = 0
138  n1 = ifabor(ielem,2)
139  IF (n1.GT.0) THEN
140  IF(ikle(n1,1).EQ.i2) ifan(ielem,2) = 3
141  IF(ikle(n1,2).EQ.i2) ifan(ielem,2) = 1
142  IF(ikle(n1,3).EQ.i2) ifan(ielem,2) = 2
143  ENDIF
144 !
145  ifan(ielem,3) = 0
146  n1 = ifabor(ielem,3)
147  IF (n1.GT.0) THEN
148  IF(ikle(n1,1).EQ.i3) ifan(ielem,3) = 3
149  IF(ikle(n1,2).EQ.i3) ifan(ielem,3) = 1
150  IF(ikle(n1,3).EQ.i3) ifan(ielem,3) = 2
151  ENDIF
152 !
153  zfe(ielem) = max(zf(i1),zf(i2),zf(i3))
154  itra01(i1,1) = ielem
155  itra02(i1) = 1
156  itra01(i2,1) = ielem
157  itra02(i2) = 2
158  itra01(i3,1) = ielem
159  itra02(i3) = 3
160 !
161  ENDDO ! IELEM
162 !
163 !-----------------------------------------------------------------------
164 !
165 ! STARTS TO FILL IN ITRA01 AND ITRA02 FOR BOUNDARY NODES
166 !
167 ! FOR THESE POINTS ITRA01(IPOIN,1) IS NOT ANY ELEMENT: IT'S THE
168 ! ELEMENT CONTAINING A BOUNDARY SIDE BETWEEN NODE IPOIN AND THE
169 ! FOLLOWING NODE IN THE LOCAL NUMBERING OF THE ELEMENT.
170 !
171 !-----------------------------------------------------------------------
172 !
173  DO iptfr = 1,nptfr
174  itra01(nbor(iptfr),1) = nelbor(iptfr)
175  itra02(nbor(iptfr)) = nulone(iptfr)
176  ENDDO ! IPTFR
177 !
178 !-----------------------------------------------------------------------
179 !
180 ! RESUMES TO FILL IN ITRA01
181 !
182 ! ITRA01(IPOIN,I+1) IS THE NUMBER OF THE ELEMENT ADJACENT TO ELEMENT
183 ! ITRA01(IPOIN,1) WHEN TURNING ANTI-CLOCKWISE AROUND POINT IPOIN.
184 ! ITRA02 IS A UNIDIMENSIONAL ARRAY BECAUSE THE LOCAL NUMBER OF IPOIN
185 ! IN ANY ELEMENT ITRA01(IPOIN,*) WILL NOT NEEDED IN THE FUTURE.
186 !
187 !
188 ! FILLS IN ITRA03
189 !
190 ! ITRA03(IPOIN) CORRESPONDS TO THE NUMBER OF ELEMENTS CONTAINING IPOIN
191 ! (WITH A NEGATIVE SIGN IF IPOIN IS A BOUNDARY NODE).
192 !
193 ! BEWARE |||
194 !
195 ! ONE POINT CAN ONLY BE PART OF A MAXIMUM OF 10 ELEMENTS
196 !
197 !-----------------------------------------------------------------------
198 !
199  DO ipoin = 1,npoin
200  itra03(ipoin) = 0
201  ENDDO ! IPOIN
202 !
203  imax = 0
204 !
205 40 CONTINUE
206  flag = .false.
207  imax = imax + 1
208  IF (imax.GT.mxptvs+1) THEN
209  WRITE(lu,24) mxptvs
210 24 FORMAT(1x,'TOPOGR : THE MAXIMUM NUMBER OF NEIGHBOURS TO'/,1x,
211  & ' A POINT IS GREATER THAN THE VALUE ',/,1x,
212  & ' GIVEN BY MXPTVS :',1i6)
213  CALL plante(0)
214  stop
215  ENDIF
216 !
217  DO ipoin = 1,npoin
218 !
219  IF (itra03(ipoin).EQ.0) THEN
220  n1 = itra01(ipoin,imax)
221  IF(n1.NE.0) THEN
222  flag = .true.
223  n2 = ifabor(n1,iprev(itra02(ipoin)))
224 ! HERE IMAX IS NEVER AT ITS MAXIMUM
225  itra01(ipoin,imax+1) = n2
226  itra02(ipoin) = ifan(n1,iprev(itra02(ipoin)))
227  IF (n2.LE.0) itra03(ipoin) = -imax
228  IF (n2.EQ.itra01(ipoin,1)) itra03(ipoin) = imax
229  ENDIF
230  ENDIF
231 !
232  ENDDO ! IPOIN
233 !
234  IF (flag) GOTO 40
235 !
236 60 CONTINUE
237 !
238 !-----------------------------------------------------------------------
239 !
240 ! DETERMINES LOCAL EXTREMA FOR ZFE BY TURNING AROUND A NODE
241 !
242 ! ITRA04(IPOIN,I) CORRESPONDS TO THE IEME EXTREMUM FOUND, WITH THE
243 ! ASSOCIATED ELEMENT GIVEN BY ITRA01(IPOIN,ITRA04(IPOIN,I)).
244 ! ITRA02(IPOIN) GIVES THE TOTAL NUMBER OF INCREASE AND DECREASE STAGES
245 ! (WITH A NEGATIVE SIGN IF THE LAST STAGE FOUND IS A DECREASE).
246 !
247 !
248 !-----------------------------------------------------------------------
249 !
250  DO ipoin = 1,npoin
251  itra02(ipoin) = 0
252  itra05(ipoin) = 0
253  ENDDO ! IPOIN
254 !
255  DO i = 1,imax-1
256 !
257  DO ipoin = 1,npoin
258 !
259  IF (itra03(ipoin).GE.i.OR.itra03(ipoin).LT.-i) THEN
260 !
261  n1 = itra01(ipoin,i)
262  n2 = itra01(ipoin,i+1)
263 !
264  IF (zfe(n2).GT.zfe(n1)+epsilo) THEN
265  IF (itra02(ipoin).LT.0) itra04(ipoin,-itra02(ipoin))=i
266  IF (itra02(ipoin).LE.0) itra02(ipoin)=-itra02(ipoin)+1
267  ELSEIF (zfe(n2).LT.zfe(n1)-epsilo) THEN
268  IF (itra02(ipoin).GT.0) itra04(ipoin, itra02(ipoin))=i
269  IF (itra02(ipoin).GE.0) itra02(ipoin)=-itra02(ipoin)-1
270  ENDIF
271 !
272  ENDIF
273 !
274  ENDDO ! IPOIN
275 !
276  ENDDO ! I
277 !
278  DO ipoin = 1,npoin
279  IF((itra03(ipoin).LT.0.AND.(itra02(ipoin).LE.-4.OR.
280  & itra02(ipoin).GE.5)).OR.abs(itra02(ipoin)).GE.6) THEN
281  WRITE(lu,*) 'THE MESH AROUND THE NODE ',ipoin,' HAS TO'
282  WRITE(lu,*) 'BE REFINED BECAUSE OF THE BATHYMETRY'
283  CALL plante(1)
284  stop
285  ENDIF
286  ENDDO ! IPOIN
287 !
288 !-----------------------------------------------------------------------
289 !
290 ! CORRECTS ZFE DEPENDING ON ITRA02
291 !
292 !-----------------------------------------------------------------------
293 !
294  flag = .false.
295 !
296  DO ipoin = 1,npoin
297 !
298  i1 = itra03(ipoin)
299 !
300  IF (i1.LT.0) THEN
301 !
302 !-----------------------------------------------------------------------
303 !
304 ! CORRECTS ZFE FOR BOUNDARY NODES
305 !
306 ! IF ITRA02(IPOIN) EQUALS 1, -1, 2 : NO CORRECTION
307 ! IF ITRA02(IPOIN) EQUALS -2, 3, -3, 4 : CORRECTION
308 !
309 !-----------------------------------------------------------------------
310 !
311  IF (itra02(ipoin).EQ.-2) THEN
312 !
313  flag = .true.
314  IF (zfe(itra01(ipoin,-i1)).GT.zfe(itra01(ipoin,1))) THEN
315  itra02(ipoin) = itra04(ipoin,1) + 1
316  itra05(ipoin) = -i1
317  ELSE
318  itra02(ipoin) = 1
319  itra05(ipoin) = itra04(ipoin,1) - 1
320  ENDIF
321  zref(ipoin) = zfe(itra01(ipoin,itra04(ipoin,1)))
322 !
323  ELSEIF (itra02(ipoin).EQ.3) THEN
324 !
325  flag = .true.
326  IF (zfe(itra01(ipoin,itra04(ipoin,2))).GT.
327  & zfe(itra01(ipoin,1))) THEN
328  itra02(ipoin) = itra04(ipoin,1) + 1
329  itra05(ipoin) = -i1
330  ELSE
331  itra02(ipoin) = 1
332  itra05(ipoin) = itra04(ipoin,1) - 1
333  ENDIF
334  zref(ipoin) = zfe(itra01(ipoin,itra04(ipoin,1)))
335 !
336  ELSEIF (itra02(ipoin).EQ.-3) THEN
337 !
338  flag = .true.
339  IF (zfe(itra01(ipoin,-i1)).GT.
340  & zfe(itra01(ipoin,itra04(ipoin,1)))) THEN
341  itra02(ipoin) = itra04(ipoin,2) + 1
342  itra05(ipoin) = -i1
343  ELSE
344  itra02(ipoin) = 1
345  itra05(ipoin) = itra04(ipoin,2) - 1
346  ENDIF
347  zref(ipoin) = zfe(itra01(ipoin,itra04(ipoin,2)))
348 !
349  ELSEIF (itra02(ipoin).EQ.4) THEN
350 !
351  flag = .true.
352  IF (zfe(itra01(ipoin,itra04(ipoin,3))).GT.
353  & zfe(itra01(ipoin,itra04(ipoin,1)))) THEN
354  itra02(ipoin) = itra04(ipoin,2) + 1
355  itra05(ipoin) = -i1
356  ELSE
357  itra02(ipoin) = 1
358  itra05(ipoin) = itra04(ipoin,2) - 1
359  ENDIF
360  zref(ipoin) = zfe(itra01(ipoin,itra04(ipoin,2)))
361 !
362  ENDIF
363 !
364  ELSE
365 !
366 !-----------------------------------------------------------------------
367 !
368 ! CORRECTS ZFE FOR INTERIOR NODES
369 !
370 ! IF ITRA02(IPOIN) EQUALS 1, -1, 2, -2, 3, -3 : NO CORRECTION
371 ! IF ITRA02(IPOIN) EQUALS 4, -4, 5, -5 : CORRECTION
372 !
373 !-----------------------------------------------------------------------
374 !
375  IF (itra02(ipoin).EQ.4) THEN
376 !
377  flag = .true.
378  IF (zfe(itra01(ipoin,itra04(ipoin,3))).GT.
379  & zfe(itra01(ipoin,itra04(ipoin,1)))) THEN
380  itra02(ipoin) = itra04(ipoin,2) + 1
381  itra05(ipoin) = i1
382  ELSE
383  itra02(ipoin) = 2
384  itra05(ipoin) = itra04(ipoin,2) - 1
385  ENDIF
386  zref(ipoin) = min(zfe(itra01(ipoin,itra04(ipoin,2))),
387  & zfe(itra01(ipoin,1)))
388 !
389  ELSEIF (itra02(ipoin).EQ.-4) THEN
390 !
391  flag = .true.
392  IF (zfe(itra01(ipoin,itra04(ipoin,2))).GT.
393  & zfe(itra01(ipoin,1))) THEN
394  itra02(ipoin) = itra04(ipoin,1) + 1
395  itra05(ipoin) = itra04(ipoin,3) - 1
396  ELSE
397  itra02(ipoin) = mod(itra04(ipoin,3),i1) + 1
398  itra05(ipoin) = itra04(ipoin,1) - 1
399  ENDIF
400  zref(ipoin) = min(zfe(itra01(ipoin,itra04(ipoin,1))),
401  & zfe(itra01(ipoin,itra04(ipoin,3))))
402 !
403  ELSEIF (itra02(ipoin).EQ.5) THEN
404 !
405  flag = .true.
406  IF (zfe(itra01(ipoin,itra04(ipoin,4))).GT.
407  & zfe(itra01(ipoin,itra04(ipoin,2)))) THEN
408  itra02(ipoin) = itra04(ipoin,3) + 1
409  itra05(ipoin) = itra04(ipoin,1) - 1
410  ELSE
411  itra02(ipoin) = itra04(ipoin,1) + 1
412  itra05(ipoin) = itra04(ipoin,3) - 1
413  ENDIF
414  zref(ipoin) = min(zfe(itra01(ipoin,itra04(ipoin,1))),
415  & zfe(itra01(ipoin,itra04(ipoin,3))))
416 !
417  ELSEIF (itra02(ipoin).EQ.-5) THEN
418 !
419  flag = .true.
420  IF (zfe(itra01(ipoin,itra04(ipoin,3))).GT.
421  & zfe(itra01(ipoin,itra04(ipoin,1)))) THEN
422  itra02(ipoin) = itra04(ipoin,2) + 1
423  itra05(ipoin) = itra04(ipoin,4) - 1
424  ELSE
425  itra02(ipoin) = mod(itra04(ipoin,4),i1) + 1
426  itra05(ipoin) = itra04(ipoin,2) - 1
427  ENDIF
428  zref(ipoin) = min(zfe(itra01(ipoin,itra04(ipoin,2))),
429  & zfe(itra01(ipoin,itra04(ipoin,4))))
430 !
431  ENDIF
432 !
433  ENDIF
434 !
435  ENDDO ! IPOIN
436 !
437  IF (flag) THEN
438 !
439  DO ipoin = 1,npoin
440 !
441  IF (itra05(ipoin).NE.0) THEN
442 !
443  IF (itra05(ipoin).LT.itra02(ipoin)) THEN
444  DO i = itra02(ipoin),itra03(ipoin)
445  zfe(itra01(ipoin,i)) = max(zfe(itra01(ipoin,i)),
446  & zref(ipoin))
447  ENDDO ! I
448  itra02(ipoin) = 1
449  ENDIF
450 !
451  DO i = itra02(ipoin),itra05(ipoin)
452  zfe(itra01(ipoin,i)) = max(zfe(itra01(ipoin,i)),
453  & zref(ipoin))
454  ENDDO ! I
455 !
456  ENDIF
457 !
458  ENDDO ! IPOIN
459 !
460  GOTO 60
461 !
462  ENDIF
463 !
464 !-----------------------------------------------------------------------
465 !
466  DEALLOCATE(ifan)
467  DEALLOCATE(itra01)
468  DEALLOCATE(itra04)
469 !
470 !-----------------------------------------------------------------------
471 !
472  RETURN
473  END
subroutine topogr(ZF, ZREF, ZFE, IKLE, IFABOR, NBOR, NELBOR, NULONE, ITRA05, ITRA02, ITRA03, NELEM, NPTFR, NPOIN, MXPTVS)
Definition: topogr.f:8