GRIDMAN
grid managment library
triang.f
Go to the documentation of this file.
1 C> @file grid2D/triang.f
2 C> Triangulation of 2D grid
3 C GRIDMAN, grid managment library. Author: Vladislav Kotov, v.kotov@fz-juelich.de
4 
5 ! Copyright (c) 2017 Forschungszentrum Juelich GmbH
6 ! Vladislav Kotov
7 !
8 ! This file is part of GRIDMAN.
9 !
10 ! GRIDMAN is free software: you can redistribute it and/or modify
11 ! it under the terms of the GNU General Public License as published by
12 ! the Free Software Foundation, either version 3 of the License, or
13 ! (at your option) any later version.
14 !
15 ! GRIDMAN is distributed in the hope that it will be useful,
16 ! but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ! GNU General Public License for more details.
19 !
20 ! You should have received a copy of the GNU General Public License
21 ! along with GRIDMAN. If not, see <http://www.gnu.org/licenses/>.
22 
23 C**********************************************************************************************
24 C> Triangulation of 2D grid
25 C>
26 C> WARNING: if the object GRID already exist it will be overwritten!
27 C> Same is true for mapping tables.
28 C>
29 C> The algorithm works iteratively. On each iteration one new edge
30 C> is added to the cells with number of vertices > 3.
31 C> Iterations stop when all cells have only 3 vertices.
32 C>
33 C> The edge is added in the following way. For each vertex
34 C> a triangle is built by connecting its both neighbour vertices.
35 C> Triangles are rejected for which:
36 C> 1. New added edge intersect other edges of the cells
37 C> 2. Basis vertex is concave
38 C> 3. Triangle area is larger than 0.51*(total cell area)
39 C>
40 C> For each triangle which is not rejected the smallest angle
41 C> is calculated. Triangle with the largest smallest angle is
42 C> finally accepted.
43 C>
44 C> Condition 3 is required to avoid the following situation:
45 C>
46 C> B Here the algorithm may choose triangle ABC
47 C> / \ which leads to "flat" triangle ACD on the other side.
48 C> / \ Condition S<0.51S_tot forces the algorithm to chose
49 C> / \ triangle ABD or BDC which leaves "non flat" rest
50 C> /___ ___\ of the cell
51 C> A D C
52 C>
53 C**********************************************************************************************
54  SUBROUTINE gridman_grid2d_triang(TRIA,GRID,IERR)
56  u gridman_dbg,gridman_check,gridman_indlist
62  IMPLICIT NONE
63  INTRINSIC trim,abs
64 C> Resulting triangular grid
65  TYPE(gridman_grid) :: TRIA
66 C> Initial grid which is divided into triangles
67  TYPE(gridman_grid) :: GRID
68 C> Error code
69  INTEGER,INTENT(OUT) :: IERR
70 
71  INTEGER :: RES,IERR0,II,ST
72  INTEGER(GRIDMAN_SP) :: ICELL,NP,NCELLS0,NEDGES0,ICELL0,
73  i dnc,dne,ncells,nedges,n,ie,i,nelements
74  INTEGER(GRIDMAN_SP),ALLOCATABLE :: IOLDCELL(:)
75  TYPE(gridman_indlist) :: CHAINS,INEWCELL
76 
77  IF(gridman_dbg)
78  f WRITE(gridman_unit,*) "Starting GRIDMAN_GRID2D_TRIANG"
79 
80  ierr=0
81 
82  IF(grid%TYPE.NE.2.OR.grid%PDIM.NE.2.OR.grid%EDIM.NE.2) THEN
83  ierr=100
84  WRITE(gridman_unit,*) "GRIDMAN_GRID2D_TRIANG: ",
85  w "the grid is not of 2D type"
86  WRITE(gridman_unit,*) " TYPE, PDIM, EDIM ",
87  w grid%TYPE,grid%PDIM,grid%EDIM
88  RETURN
89  END IF
90 
91  IF(grid%NCELLS.LT.1) GOTO 100
92 
93  IF(gridman_check) THEN
94  CALL gridman_grid2d_check(grid,res,ierr)
95  IF(res.NE.0.OR.ierr.GT.0) THEN
96  ierr=100
97  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
98  w "incorrect input grid"
99  RETURN
100  END IF
101  END IF
102 
103 C CALCULATE THE NUMBER OF CELLS AND EDGES IN THE TRIANGULATED GRID
104  CALL gridman_grid2d_chains(grid,chains,ierr)
105  IF(ierr.GT.0) GOTO 150
106  ncells=grid%NCELLS
107  nedges=grid%NEDGES
108  DO icell=1,chains%N
109  np=chains%ILAST(icell)-chains%IFIRST(icell) !NUMBER OF POINTS
110  IF(np.LT.3) GOTO 200
111  ncells=ncells+np-3
112  nedges=nedges+np-3
113  END DO
114 C ALLOCATE GRID
115  CALL gridman_grid_allocate(tria,grid%TYPE,nedges,grid%NPOINTS,
116  s ncells,ierr,grid%NEDGEINDEX)
117  IF(ierr.GT.0) GOTO 1000
118 C TAKE POINTS AND EDGES OF THE INITIAL GRID INTO NEW GRID
119  CALL gridman_grid_take(tria,grid,ierr)
120  IF(ierr.GT.0) GOTO 1000
121 C EDGE INDEXES - OLD EDGES ARE NOT CHANGED
122  DO ii=1,grid%NEDGEINDEX
123  CALL gridman_index_copy(tria%EDGEINDEX(ii),
124  c grid%EDGEINDEX(ii),ierr)
125  IF(ierr.NE.0) GOTO 600
126  END DO
127 C RESET CURRENT NUMBER OF CELLS AND EDGES IN THE NEW GRID
128  ncells0=grid%NCELLS
129  nedges0=grid%NEDGES
130  tria%NCELLS=grid%NCELLS
131  tria%NEDGES=grid%NEDGES
132  IF(grid%NCELLINDEX.GT.0) THEN
133 C ALLOCATE TEMPORARY ARRAY
134  ALLOCATE(ioldcell(ncells),stat=st)
135  IF(st.NE.0) GOTO 300
136  DO icell=1,ncells
137  ioldcell(icell)=icell
138  END DO
139  END IF
140 
141  77 CONTINUE
142 C ONE STEP OF TRIANGULATION: EACH (NON-TRIANGLE) CELL
143 C IS DIVIDED INTO A TRIANGLE AND THE REST
144  IF(ALLOCATED(ioldcell)) THEN
145  CALL gridman_grid2d_triang_step(tria,ncells,nedges,chains,ierr,
146  c ioldcell)
147  ELSE
148  CALL gridman_grid2d_triang_step(tria,ncells,nedges,chains,ierr)
149  END IF
150  IF(ierr.GT.0) GOTO 1000
151 C DIFFERENCE BETWEEN OLD AND NEW NUMBER OF CELLS (AND EDGES)
152  dnc=tria%NCELLS-ncells0
153  dne=tria%NEDGES-nedges0
154  IF(dnc.LT.0.OR.dne.LT.0.OR.dnc.NE.dne) GOTO 400
155 C IF NON-ZERO INCREMENT - THEN GO FOR THE NEXT STEP
156  IF(dnc.GT.0) THEN
157  ncells0=tria%NCELLS
158  nedges0=tria%NEDGES
159  CALL gridman_grid2d_chains(tria,chains,ierr)
160  IF(ierr.GT.0) GOTO 1000
161  GOTO 77
162  END IF
163 
164  CALL gridman_indlist_deallocate(chains,ierr0)
165 
166 C CHECK
167  IF(tria%NCELLS.NE.ncells.OR.tria%NEDGES.NE.nedges) GOTO 500
168 
169 C CELL INDEXES
170  IF(ALLOCATED(ioldcell)) THEN
171  CALL gridman_indlist_allocate(inewcell,ncells0,ncells,ierr)
172  IF(ierr.NE.0) GOTO 700
173  n=0
174  DO icell0=1,ncells0
175  inewcell%IFIRST(icell0)=n+1
176  DO icell=1,ncells
177  IF(icell0.EQ.ioldcell(icell)) THEN
178  n=n+1
179  IF(n.GT.ncells) GOTO 710
180  inewcell%IND(n)=icell
181  END IF
182  END DO
183  inewcell%ILAST(icell0)=n
184  END DO
185  IF(n.NE.ncells) GOTO 720
186  DEALLOCATE(ioldcell)
187  ALLOCATE(tria%CELLINDEX(grid%NCELLINDEX),stat=st)
188  IF(st.NE.0) GOTO 725
189  tria%NCELLINDEX=grid%NCELLINDEX
190  DO ii=1,grid%NCELLINDEX
191  nelements=0
192  DO ie=1,grid%CELLINDEX(ii)%NELEMENTS
193  icell0=grid%CELLINDEX(ii)%INDEXES(0,ie)
194  nelements=nelements+inewcell%ILAST(icell0)
195  - -inewcell%IFIRST(icell0)+1
196  END DO
197  CALL gridman_index_allocate(tria%CELLINDEX(ii),
198  c grid%CELLINDEX(ii)%NINDEX,
199  c nelements,ierr)
200  IF(ierr.GT.0) GOTO 1000
201  n=0
202  DO ie=1,grid%CELLINDEX(ii)%NELEMENTS
203  icell0=grid%CELLINDEX(ii)%INDEXES(0,ie)
204  DO i=inewcell%IFIRST(icell0),inewcell%ILAST(icell0)
205  icell=inewcell%IND(i)
206  n=n+1
207  IF(n.GT.tria%CELLINDEX(ii)%NELEMENTS) GOTO 730
208  tria%CELLINDEX(ii)%INDEXES(0,n)=icell
209  tria%CELLINDEX(ii)%INDEXES(1:,n)=
210  = grid%CELLINDEX(ii)%INDEXES(1:,ie)
211  END DO
212  END DO
213  IF(n.NE.tria%CELLINDEX(ii)%NELEMENTS) GOTO 730
214  tria%CELLINDEX(ii)%DESCRIPTION=grid%CELLINDEX(ii)%DESCRIPTION
215  tria%CELLINDEX(ii)%COLUMNS=grid%CELLINDEX(ii)%COLUMNS
216  END DO
217  CALL gridman_indlist_deallocate(inewcell,ierr0)
218  END IF !IF(ALLOCATED(IOLDCELL))
219 
220 C META DATA
221  tria%DESCRIPTION=trim(grid%DESCRIPTION)//
222  / " >> triangulated by GRIDMAN_GRID2D_TRIANG"
223 C (UNITS were written in GRIDMAN_GRID_TAKE)
224 
225  IF(gridman_check) THEN
226  CALL gridman_grid2d_check(tria,res,ierr)
227  IF(res.NE.0.OR.ierr.GT.0) THEN
228  ierr=400
229  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
230  w "wrong resulting grid"
231  END IF
232  END IF
233 
234  IF(gridman_dbg)
235  f WRITE(gridman_unit,*) "GRIDMAN_GRID2D_TRIANG finished"
236 
237  RETURN
238 
239  100 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
240  w "grid has no cells"
241  ierr=100
242  RETURN
243 
244  150 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
245  w "cannon create temporar index list CHAINS"
246  RETURN
247 
248  200 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
249  w "internal error"
250  WRITE(gridman_unit,*)
251  w " Cell has less than 3 points, ICELL ",icell
252  ierr=400
253  CALL gridman_indlist_deallocate(chains,ierr0)
254  RETURN
255 
256  300 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
257  w "cannot allocate temporary array"
258  ierr=200
259  RETURN
260 
261  400 ierr=400
262  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
263  w "internal error"
264  WRITE(gridman_unit,*)
265  w " Wrong increment of the number of edges or cells"
266  WRITE(gridman_unit,*) " NCELLS, NCELLS0 ",tria%NCELLS,ncells0
267  WRITE(gridman_unit,*) " NEDGES, NEDGES0 ",tria%NEDGES,nedges0
268  CALL gridman_indlist_deallocate(chains,ierr0)
269  IF(ALLOCATED(ioldcell)) DEALLOCATE(ioldcell)
270  RETURN
271 
272  500 ierr=400
273  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
274  w "mismatch between expected and actual grid size"
275  WRITE(gridman_unit,*) "Expected: NCELLS, NEDGES ",ncells,nedges
276  WRITE(gridman_unit,*) "Actual: NCELLS, NEDGES ",
277  w tria%NCELLS,tria%NEDGES
278  IF(ALLOCATED(ioldcell)) DEALLOCATE(ioldcell)
279 
280  600 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
281  w "cannon create edge index II ",ii
282  IF(ALLOCATED(ioldcell)) DEALLOCATE(ioldcell)
283  CALL gridman_indlist_deallocate(chains,ierr0)
284  RETURN
285 
286  700 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
287  w "cannon create temporar index list INEWCELL"
288  RETURN
289 
290  710 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
291  w "internal error - wrong IOLDCELL"
292  WRITE(gridman_unit,*) " ICELL0, ICELL, N, NCELLS ",
293  w icell0,icell,n,ncells
294  ierr=410
295  CALL gridman_indlist_deallocate(inewcell,ierr0)
296  IF(ALLOCATED(ioldcell)) DEALLOCATE(ioldcell)
297  RETURN
298  720 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
299  w "internal error - wrong IOLDCELL"
300  WRITE(gridman_unit,*) " It must be N==NCELLS, N, NCELLS ",n,ncells
301  ierr=420
302  CALL gridman_indlist_deallocate(inewcell,ierr0)
303  IF(ALLOCATED(ioldcell)) DEALLOCATE(ioldcell)
304  RETURN
305  725 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
306  w "cannot allocate TRIA%CELLINDEX"
307  WRITE(gridman_unit,*) " NCELLINDEX ",grid%NCELLINDEX
308  ierr=200
309  RETURN
310  730 WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_TRIANG: ",
311  w "internal error - unexpected cell index"
312  WRITE(gridman_unit,*) " II, N, NELEMENTS ",ii,n,nelements
313  ierr=430
314  CALL gridman_indlist_deallocate(inewcell,ierr0)
315  IF(ALLOCATED(ioldcell)) DEALLOCATE(ioldcell)
316  RETURN
317 
318  1000 CALL gridman_indlist_deallocate(chains,ierr0)
319  IF(ALLOCATED(ioldcell)) DEALLOCATE(ioldcell)
320  WRITE(gridman_unit,*) "GRIDMAN_GRID2D_TRIANG is terminated"
321 
322  CONTAINS
323 C
324 C ONE STEP OF TRIANGULATION
325 C EACH (NON-TRUANGLE) CELL IS DIVIDED INTO A TRIANGLE AND THE REST
326 C
327 C
328  SUBROUTINE gridman_grid2d_triang_step(GRID,NCELLS_MAX,NEDGES_MAX,
329  c chains,ierr,ioldcell)
330  USE gridman,ONLY:gridman_dp
332  INTRINSIC tiny
333  TYPE(gridman_grid) :: GRID
334  INTEGER(GRIDMAN_SP),INTENT(IN) :: NCELLS_MAX,NEDGES_MAX
335  TYPE(gridman_indlist) :: CHAINS
336  INTEGER,INTENT(OUT) :: IERR
337  INTEGER(GRIDMAN_SP),OPTIONAL :: IOLDCELL(ncells_max)
338 
339  INTEGER(GRIDMAN_SP) :: ICELL,IPOINT(3),IP1,IP,IP2,I,N,ID,IE,IEDGE,
340  i ncells0,ncells,nedges,npmax,np,st
341  INTEGER :: IERR0
342  REAL(GRIDMAN_DP) :: VTVS,VTVT,STOT,MMCOS
343  REAL(GRIDMAN_DP) :: X(3),Y(3)
344  TYPE(gridman_indlist) :: CELLS
345 C ARRAYS WHICH STORE CANDIDADE NEW EDGES
346  INTEGER(GRIDMAN_DP),ALLOCATABLE :: IEP(:,:)
347  REAL(GRIDMAN_DP),ALLOCATABLE :: VTV(:),S(:),MAXCOS(:)
348 
349  IF(gridman_dbg)
350  f WRITE(gridman_unit,*) "Starting GRIDMAN_GRID2D_TRIANG_STEP"
351 
352  ierr=0
353 
354 C DETERMINE THE MAXIMAL NUMBER OF POINTS (EDGES) OF THE CELLS
355  npmax=0
356  DO icell=1,chains%N
357  np=chains%ILAST(icell)-chains%IFIRST(icell)
358  IF(np.GT.npmax) npmax=np
359  END DO
360 
361 C ALLOCATE TEMPORARY ARRAYS
362  ALLOCATE(iep(3,npmax),vtv(npmax),s(npmax),maxcos(npmax),stat=st)
363  IF(st.NE.0) THEN
364  ierr=200
365  WRITE(gridman_unit,*) "Erroor in GRIDMAN_GRID2D_TRIANG_STEP: ",
366  w "can not allocate temporary arrays"
367  GOTO 500
368  END IF
369 
370 C ARRAY OF EDGES FOR EACH CELL
371  CALL gridman_grid_cells(cells,grid,ierr)
372  IF(ierr.GT.0) GOTO 500
373 
374  ncells=grid%NCELLS
375  nedges=grid%NEDGES
376  ncells0=ncells
377  DO icell=1,ncells0 !CYCLE OVER CELLS
378  n=chains%ILAST(icell)-chains%IFIRST(icell) !NUMBER OF EDGES
379  IF(n.LT.4) cycle !SKIP TRIANGLES
380  vtvs=0.
381  stot=0.
382  n=0
383  ip1=chains%ILAST(icell)-1
384  DO ip=chains%IFIRST(icell),chains%ILAST(icell)-1
385 C EDGE WHICH CONNECTS IP1 AND IP+1
386 C CHECK FOR INTERSECTIONS WITH OTHER EDGES OF THIS CELL
387  ipoint(1)=chains%IND(ip1)
388  ipoint(2)=chains%IND(ip)
389  ipoint(3)=chains%IND(ip+1)
390  x(1:3)=grid%X(1,ipoint(1:3))
391  y(1:3)=grid%X(2,ipoint(1:3))
392  vtvt=(x(2)-x(1))*(y(3)-y(2))-(x(3)-x(2))*(y(2)-y(1))
393  vtvs=vtvs+vtvt
394  stot=stot+(x(3)+x(2))*(y(3)-y(2))
395  IF(self_intersections(ipoint(1),ipoint(3),icell)) THEN
396  ip1=ip
397  cycle
398  END IF
399 C ADD EDGE (IPOINT1,IPOINT3) INTO TEMPORARY ARRAY
400  n=n+1
401  iep(1:3,n)=ipoint(1:3)
402 C PERPENDICULAR DOT PRODUCT: TO FIND OUT IF THE VERTEX IS CONVEX
403  vtv(n)=vtvt
404 C AREAS OF THE RESULTING TRIANGLES
405  s(n)=(x(3)+x(2))*(y(3)-y(2))+
406  + (x(2)+x(1))*(y(2)-y(1))+(x(1)+x(3))*(y(1)-y(3))
407 C MAX COSINUS (SMALLEST ANGLE)
408  maxcos(n)=maximum_cosine(x,y)
409  IF(maxcos(n).LT.-1.0) THEN
410  ierr=100
411  GOTO 500
412  END IF
413 C
414  ip1=ip
415  END DO !DO IP=CHAINS%IFIRST(ICELL),CHAINS%ILAST(ICELL)-1
416 C
417 C TEMPORARY ARRAY CONTAINS THE CANDIDADE EDGES
418 C THE ONE WILL BE CHOSEN FOR WHICH
419 C 1. THE VORTEX IS CONCAVE
420 C 2. THE TRIANGLE AREA S IS SMALLER THAT 0.51*STOT
421 C
422 C AMONG THOSE THE ONE WITH THE LARGEST SMALLEST ANGLE IS TAKEN
423 C
424  mmcos=2.0
425  stot=0.51*abs(stot)
426  id=0
427  DO i=1,n
428  IF(( vtvs.LT.0.AND.vtv(i).GT.-tiny(vtvs)).OR. !CLOCKWISE DIRECTION
429  f ( vtvs.GT.0.AND.vtv(i).LT.tiny(vtvs)).OR. !COUNTER-CLOCKWISE
430  f abs(s(i)).GT.stot) cycle !SKIP CONVEX CORNERS AND TOO LARGE CELLS
431  IF(maxcos(i).LT.mmcos) THEN
432  ipoint(1:3)=iep(1:3,i)
433  id=id+1
434  mmcos=maxcos(i)
435  END IF
436  END DO
437  IF(id.EQ.0) THEN
438  ierr=400
439  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2_TRIANG_STEP: ",
440  w "internal error - no new edges found"
441  WRITE(gridman_unit,*) " ICELL, N ",icell,n
442  WRITE(gridman_unit,*) " MAXCOS ",maxcos(1:n)
443  WRITE(gridman_unit,*) " STOT, S ",stot,abs(s(1:n))
444  GOTO 500
445  END IF
446 C ADD NEW EDGE AND NEW CELL
447  ncells=ncells+1
448  nedges=nedges+1
449  IF(ncells.GT.ncells_max.OR.nedges.GT.nedges_max) THEN
450  ierr=400
451  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2_TRIANG_STEP: ",
452  w "internal error - index exceeds the maximum"
453  WRITE(gridman_unit,*) " ICELL ",icell
454  WRITE(gridman_unit,*) " NCELLS, NCELLS_MAX ",ncells,ncells_max
455  WRITE(gridman_unit,*) " NEDGES, NEDGES_MAX ",nedges,nedges_max
456  GOTO 500
457  END IF
458  grid%CELLS(1,nedges)=icell
459  grid%CELLS(2,nedges)=ncells
460  grid%POINTS(1,nedges)=ipoint(1)
461  grid%POINTS(2,nedges)=ipoint(3)
462 C CORRECT CELL INDEX FOR TWO OLD EDGES OF THE NEW TRIANGLE
463  DO ie=cells%IFIRST(icell),cells%ILAST(icell)
464  iedge=cells%IND(ie)
465  IF(iedge.LT.1.OR.iedge.GT.nedges_max) THEN
466  ierr=400
467  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2_TRIANG_STEP: ",
468  w "internal erorr - edge index out of range"
469  WRITE(gridman_unit,*) " ICELL, IEDGE, NEDGES_MAX ",
470  w icell, iedge, nedges_max
471  END IF
472  ip1=grid%POINTS(1,iedge)
473  ip2=grid%POINTS(2,iedge)
474  DO i=1,2
475  IF((ip1.EQ.ipoint(i).AND.ip2.EQ.ipoint(i+1)).OR.
476  f (ip2.EQ.ipoint(i).AND.ip1.EQ.ipoint(i+1))) THEN
477  IF(grid%CELLS(1,iedge).EQ.icell ) THEN
478  grid%CELLS(1,iedge)=ncells
479  cycle
480  ELSE IF(grid%CELLS(2,iedge).EQ.icell ) THEN
481  grid%CELLS(2,iedge)=ncells
482  cycle
483  ELSE
484  ierr=400
485  WRITE(gridman_unit,*)
486  w "ERROR in GRIDMAN_GRID2_TRIANG_STEP: ",
487  w "internal erorr - cell index mismatch"
488  WRITE(gridman_unit,*) " ICELL, IEDGE ",icell,iedge
489  WRITE(gridman_unit,*) " IPOINT1, IPOINT2 ",
490  w ipoint(i),ipoint(i+1)
491  WRITE(gridman_unit,*) " IP1, IP2 ",ip2,ip2
492  WRITE(gridman_unit,*) " CELLS ",grid%CELLS(:,iedge)
493  GOTO 500
494  END IF
495  END IF
496  END DO
497  END DO
498  grid%NCELLS=ncells
499  grid%NEDGES=nedges
500  IF(PRESENT(ioldcell)) ioldcell(ncells)=ioldcell(icell)
501  END DO !DO ICELL=1,NCELLS
502 
503  DEALLOCATE(iep,vtv,s,maxcos,stat=st)
504  IF(st.NE.0) THEN
505  ierr=-200
506  WRITE(gridman_unit,*)
507  w "Warning from GRIDMAN_GRID2D_TRIANG_STEP ",
508  w "could not deallocate temporary arrays"
509  END IF
510  CALL gridman_indlist_deallocate(cells,ierr)
511 
512  IF(gridman_dbg)
513  f WRITE(gridman_unit,*) "GRIDMAN_GRID2_TRIANG_STEP finished"
514 
515  RETURN
516 
517  500 DEALLOCATE(iep,vtv,s,maxcos,stat=st)
518  CALL gridman_indlist_deallocate(cells,ierr0)
519  WRITE(gridman_unit,*) "GRIDMAN_GRID2_TRIANG_STEP terminated"
520  RETURN
521 
522  END SUBROUTINE gridman_grid2d_triang_step
523 
524 C
525 C CALCULATE LARGEST COSINE OF THE TRIANGLES ANGLES:
526 C THAT IS, COSINE OF THE SMALLEST ANGLE
527 C
528  FUNCTION maximum_cosine(X,Y)
529  USE gridman,ONLY:gridman_dp
530  REAL(GRIDMAN_DP),INTENT(IN) :: X(3),Y(3)
531  REAL(GRIDMAN_DP) :: MAXIMUM_COSINE
532  REAL(GRIDMAN_DP) :: VX(3),VY(3),V(3),CS
533  INTEGER :: I,I1
534 
535  INTRINSIC sqrt
536 
537  maximum_cosine=-2.0
538  DO i=1,3
539  i1=i+1
540  IF(i1.GT.3) i1=1
541  vx(i)=x(i1)-x(i)
542  vy(i)=y(i1)-y(i)
543  v(i)=sqrt(vx(i)**2+vy(i)**2)
544  IF(.NOT.v(i).GT.tiny(cs)) THEN
545  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2_TRIANG: ",
546  w "edge has zero length"
547  WRITE(gridman_unit,*) " X ",x
548 
549  WRITE(gridman_unit,*) " Y ",y
550 
551  RETURN
552  END IF
553  END DO
554  DO i=1,3
555  i1=i+1
556  IF(i1.GT.3) i1=1
557  cs=vx(i)*vx(i1)+vy(i)*vy(i1)
558  cs=-cs/(v(i)*v(i1))
559  IF(cs.GT.maximum_cosine) maximum_cosine=cs
560  END DO
561 
562  END FUNCTION maximum_cosine
563 
564 C
565  FUNCTION self_intersections(IPOINT10,IPOINT20,ICELL)
566  USE gridman,ONLY:gridman_dp
568  INTEGER(GRIDMAN_SP),INTENT(IN) :: IPOINT10,IPOINT20,ICELL
569  LOGICAL :: SELF_INTERSECTIONS
570  REAL(GRIDMAN_DP) :: X01,X02,Y01,Y02,X1,X2,Y1,Y2,XI,YI
571  INTEGER(GRIDMAN_SP) :: IP,IPOINT1,IPOINT2
572 
573  x01=grid%X(1,ipoint10)
574  y01=grid%X(2,ipoint10)
575  x02=grid%X(1,ipoint20)
576  y02=grid%X(2,ipoint20)
577  DO ip=chains%IFIRST(icell),chains%ILAST(icell)-1
578  ipoint1=chains%IND(ip)
579  ipoint2=chains%IND(ip+1)
580  IF(ipoint1.EQ.ipoint10.OR.ipoint1.EQ.ipoint20.OR.
581  f ipoint2.EQ.ipoint10.OR.ipoint2.EQ.ipoint20) cycle
582  x1=grid%X(1,ipoint1)
583  y1=grid%X(2,ipoint1)
584  x2=grid%X(1,ipoint2)
585  y2=grid%X(2,ipoint2)
586  IF(gridman_intersect2d(x01,y01,x02,y02,
587  f x1,y1,x2,y2,xi,yi)) THEN
588  self_intersections=.true.
589  RETURN
590  END IF
591  END DO
592  self_intersections=.false.
593 
594  END FUNCTION self_intersections
595 
596  END SUBROUTINE gridman_grid2d_triang
subroutine gridman_grid_check(GRID, RES, IERR)
Check consistency of the grid data.
Definition: grid1.f:289
logical function gridman_intersect2d(X11, Y11, X12, Y12, X21, Y21, X22, Y22, XI, YI)
Intersection of two intervals on a plane.
Definition: geom.f:167
subroutine gridman_indlist_allocate(INDLIST, N, L, IERR)
Allocate list of elements.
Definition: indlist.f:32
integer, save, public gridman_unit
Index of the standard output unit.
Definition: gridman.f:116
integer, parameter, public gridman_dp
Kind parameter for real numbers.
Definition: gridman.f:93
Explicit interfaces to GRIDMAN subroutines and functions.
Definition: gridman.f:251
subroutine gridman_grid_allocate(GRID, TYPE, NEDGES, NPOINTS, NCELLS, IERR, NEDGEINDEX, NCELLINDEX)
Allocate GRIDMAN_GRID object.
Definition: grid1.f:30
subroutine gridman_grid2d_chains(GRID, CHAINS, IERR)
Find closed chain of points which form each cell.
Definition: grid2d.f:266
subroutine gridman_index_copy(INDEX2, INDEX1, IERR)
Create a copy of the index object.
Definition: index.f:538
subroutine gridman_grid_cells(EDGES, GRID, IERR)
Create a list of edges which belong to each cell.
Definition: grid2.f:177
subroutine gridman_grid_take(GRID2, GRID1, IERR)
Take data from one grid object to another.
Definition: grid1.f:1283
subroutine gridman_grid2d_check(GRID, RES, IERR)
Check correctness of the 2D grid object.
Definition: grid2d.f:37
subroutine gridman_indlist_deallocate(INDLIST, IERR)
Deallocate list of indices.
Definition: indlist.f:106
Data-type which describes a grid as a set of edges, methods in grid.f.
Definition: gridman.f:168
subroutine gridman_grid2d_triang(TRIA, GRID, IERR)
Triangulation of 2D grid.
Definition: triang.f:55
subroutine gridman_index_allocate(INDEX, NINDEX, NELEMENTS, IERR)
Allocate index object.
Definition: index.f:28
Data-type which describes lists of elements with variable number of indices for each element...
Definition: gridman.f:225
Definition of data types, global constants and variables.
Definition: gridman.f:83
integer, parameter, public gridman_sp
Kind parameter for integer numbers.
Definition: gridman.f:95