GRIDMAN
grid managment library
merge.f
Go to the documentation of this file.
1 C> @file grid2D/merge.f
2 C> Merge two 2D grids
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> Merge two 2D grids by connecting their boundary edges
24 C>
25 C> GRID2 is merged into GRID1 by connecting their boundary edges.
26 C>
27 C> WARNING: the object GRID must not be equal to GRID1 or GRID2!
28 C>
29 C> WARNING: The object GRID will be overwritten if already exists!
30 C>
31 C> WARNING: the algorithm implemented at the moment assumes
32 C> that edges of GRID1 and GRID2 which overlap with each over
33 C> can be completely removed. That is, there are no
34 C> "hanging tails" which do not belong to the intersection
35 C>
36 C> Units of GRID are same as units of GRID1
37 C
38  SUBROUTINE gridman_grid2d_merge(GRID,GRID1,GRID2,TOL,IERR)
40  u gridman_unit,gridman_dbg,gridman_check
43  IMPLICIT NONE
44  INTRINSIC sqrt,huge,max,trim,tiny
45 C> Resulting grid object
46  TYPE(gridman_grid) :: GRID
47 C> First grid which stays intact
48  TYPE(gridman_grid) :: GRID1
49 C> Second grid which is merged into the first one
50  TYPE(gridman_grid) :: GRID2
51 C> Relative accuracy of the points coordinates
52 C>
53 C> - If TOL is too large than the code can mistakenly take two different points for one point
54 C> - If TOL is too small then the code cannot recognise a point which is same in both grids
55 C>
56 C> Recommended value TOL=1e-5.
57 C> It might be necessary to increase or decrease TOL in each individual case.
58  REAL(GRIDMAN_DP),INTENT(IN) :: TOL
59 C> Error code
60  INTEGER,INTENT(OUT) :: IERR
61 
62  INTEGER(GRIDMAN_SP) ::
63  i iedge,iedge1,iedge2,nedges,enedges,nedges0,
64  i p(2),q(2),npoints,ipoint,ind(6),
65  i ipoint1,ipoint2, npoints1,ncells,tpq(2,2),
66  i points(2,2*grid1%NEDGES+2*grid2%NEDGES),!TEMPORARY ARRAY FOR POINT INDICES
67  i cells(2,2*grid1%NEDGES+2*grid2%NEDGES), !TEMPORARY ARRAY FOR CELL INDICES
68  i mapp(grid2%NPOINTS), !INDEX OF POINT IN COMBINED GRID FOR EACH POINT IN GRID2
69  i rpoints(grid2%NPOINTS)
70  INTEGER(GRIDMAN_SP) ::
71  i imape1(2,grid1%NEDGES+grid2%NEDGES), !MAPPING OF THE EDGES OF GRID TO GRID1
72  i imape2(2,grid1%NEDGES+grid2%NEDGES), !MAPPING OF THE EDGES OF GRID TO GRID2
73  i lmap0(max(grid1%NEDGES,grid2%NEDGES)) !MAPPING OF GRID1,2 TO GRID
74  INTEGER :: RES,IERR0,NEDGEINDEX,NCELLINDEX,II,II2
75 
76  LOGICAL MEDGE1(grid1%nedges),MEDGE2(grid2%nedges)
77 
78  REAL(GRIDMAN_DP) :: LE1(grid1%nedges), !LENGTH COVERED BY THE INTERSECTION FOR EACH EDGE:
79  r le2(grid2%NEDGES) !TO CHECK IF INTERSECTION COVERS THE WHOLE EDGE
80  REAL(GRIDMAN_DP) :: XP(2),YP(2),XQ(2),YQ(2),
81  r x1,y1,x2,y2,dlp,dlq,fscl,dlt,eps
82 
83  IF(gridman_dbg)
84  f WRITE(gridman_unit,*) "Starting GRIDMAN_GRID2D_MERGE"
85 
86  ierr=0
87 
88  IF(grid1%TYPE.NE.2.OR.grid1%PDIM.NE.2.OR.grid1%EDIM.NE.2) THEN
89  ierr=100
90  WRITE(gridman_unit,*) "GRIDMAN_GRID2D_TRIANG: ",
91  w "1st grid is not of 2D type"
92  WRITE(gridman_unit,*) " TYPE, PDIM, EDIM ",
93  w grid1%TYPE,grid1%PDIM,grid1%EDIM
94  RETURN
95  END IF
96 
97  IF(grid2%TYPE.NE.2.OR.grid2%PDIM.NE.2.OR.grid2%EDIM.NE.2) THEN
98  ierr=100
99  WRITE(gridman_unit,*) "GRIDMAN_GRID2D_TRIANG: ",
100  w "1st grid is not of 2D type"
101  WRITE(gridman_unit,*) " TYPE, PDIM, EDIM ",
102  w grid2%TYPE,grid2%PDIM,grid2%EDIM
103  RETURN
104  END IF
105 
106  IF(gridman_check) THEN
107  CALL gridman_grid2d_check(grid1,res,ierr)
108  IF(res.NE.0.OR.ierr.GT.0) THEN
109  ierr=100
110  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
111  w "incorrect GRID1"
112  RETURN
113  END IF
114  CALL gridman_grid2d_check(grid2,res,ierr)
115  IF(res.NE.0.OR.ierr.GT.0) THEN
116  ierr=100
117  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
118  w "incorrect GRID2"
119  RETURN
120  END IF
121  END IF
122 
123  eps=10.*tiny(eps) !MACHINE PRECISION
124 C FACTOR TO RESCALE UNITS OF GRID2 INTO UNITS OF GRID1
125  IF(grid1%UNIT2SI.LT.eps) THEN
126  ierr=100
127  WRITE(gridman_unit,*) "ERROR detected in GRIDMAN_GRID2D_MERGE: ",
128  w "wrong unit scale"
129  WRITE(gridman_unit,*) " GRID1%UNIT2SI ",grid1%UNIT2SI
130  RETURN
131  END IF
132  fscl=grid2%UNIT2SI/grid1%UNIT2SI
133 
134 C
135 C COLLECT INTERSECTING EDGES AND THEIR NON-INTERSECTING PARTS
136 C
137  rpoints=0 !NEW INDICES OF TNE POINTS IN GRID2
138  npoints=grid1%NPOINTS
139  ncells=grid1%NCELLS
140  nedges=0
141  enedges=0
142  medge1=.true.
143  medge2=.true.
144  le1=0.0
145  le2=0.0
146  DO iedge1=1,grid1%NEDGES
147  IF(grid1%CELLS(1,iedge1).GT.0.AND.
148  f grid1%CELLS(2,iedge1).GT.0) cycle !SKIP NON-BOUNDARY EDGES
149 C TAKE EDGE OF GRID1
150  p(1)=grid1%POINTS(1,iedge1)
151  p(2)=grid1%POINTS(2,iedge1)
152  xp(1)=grid1%X(1,p(1))
153  yp(1)=grid1%X(2,p(1))
154  xp(2)=grid1%X(1,p(2))
155  yp(2)=grid1%X(2,p(2))
156  DO iedge2=1,grid2%NEDGES
157  IF(grid2%CELLS(1,iedge2).GT.0.AND.
158  f grid2%CELLS(2,iedge2).GT.0) cycle
159 C TAKE EDGE OF GRID2
160  q(1)=grid2%POINTS(1,iedge2)
161  q(2)=grid2%POINTS(2,iedge2)
162  xq(1)=grid2%X(1,q(1))*fscl
163  yq(1)=grid2%X(2,q(1))*fscl
164  xq(2)=grid2%X(1,q(2))*fscl
165  yq(2)=grid2%X(2,q(2))*fscl
166 C SHIFT FOR THE INDICES OF THE POINTS OF GRID2
167  q(1)=q(1)+npoints
168  q(2)=q(2)+npoints
169 C CHECK IF TWO EDGES OVERLAP
170  CALL find_overlap(p,q,xp,yp,xq,yq,tol,ind,tpq)
171 C
172 C IND(1) -- HANGING -- IND(2)-IND(3) -- OVERLAP --IND(4)-IND(5) -- HANGING -- IND(6)
173 C
174 C IND(3) ALWAYS CORRESPONDS TO Q(1), IND(4) ALWAYS CORRESPONDS TO Q(2)
175  IF(ind(3).GT.0.AND.ind(4).GT.0) THEN
176 C OVERLAP FOUND, ADD AS NEW EDGE
177  nedges=nedges+1
178  points(1,nedges)=ind(3)
179  points(2,nedges)=ind(4)
180  cells(1,nedges)=nonzer_cell(grid1%CELLS(:,iedge1))
181  cells(2,nedges)=nonzer_cell(grid2%CELLS(:,iedge2))
182  IF(cells(2,nedges).GT.0) cells(2,nedges)=cells(2,nedges)+ncells
183  medge1(iedge1)=.false. !EDGES WHICH MUST BE EXCLUDED
184  medge2(iedge2)=.false.
185 C FOR CHECKS
186 C LENGTHS OF THE OVERLAP
187  ipoint1=ind(3)
188  IF(ipoint1.GT.npoints) THEN
189  x1=grid2%X(1,ipoint1-npoints)*fscl
190  y1=grid2%X(2,ipoint1-npoints)*fscl
191  ELSE
192  x1=grid1%X(1,ipoint1)
193  y1=grid1%X(2,ipoint1)
194  END IF
195  ipoint2=ind(4)
196  IF(ipoint2.GT.npoints) THEN
197  x2=grid2%X(1,ipoint2-npoints)*fscl
198  y2=grid2%X(2,ipoint2-npoints)*fscl
199  ELSE
200  x2=grid1%X(1,ipoint2)
201  y2=grid1%X(2,ipoint2)
202  END IF
203  dlp=sqrt((x1-x2)**2+(y1-y2)**2)
204  le1(iedge1)=le1(iedge1)+dlp
205  le2(iedge2)=le2(iedge2)+dlp
206 C FOR MAPPING
207  imape1(1,nedges)=iedge1
208  imape1(2,nedges)=nedges
209  imape2(1,nedges)=iedge2
210  imape2(2,nedges)=nedges
211  END IF !IF(IND(3).GT.0.AND.IND(4).GT.0)
212 C REPLACE POINTS IN GRID2 BY POINTS OF GRID1, IF NECESSARY
213  ipoint1=tpq(2,1)
214  ipoint2=tpq(2,2)
215  IF(ipoint1.GT.0) rpoints(tpq(1,1)-npoints)=ipoint1
216  IF(ipoint2.GT.0) rpoints(tpq(1,2)-npoints)=ipoint2
217 C "HANGING EDGES" ARE NOT SAVED IN THE CURRENT IMPLEMENTATION
218  END DO !DO IEDGE2=1,GRID2%NEDGES
219  END DO !DO IEDGE1=1,GRID1%NEDGES
220 
221  IF(nedges.EQ.0) THEN
222  WRITE(gridman_unit,*) "WARNING from GRIDMAN_GRID2D_MERGE:",
223  w " grids are not attached (no common edges)"
224  ierr0=-400
225  ELSE
226  ierr0=0
227  END IF
228 
229 C CHECK THAT OVERLAPED POINTS ARE CORRECT
230  DO ipoint2=1,grid2%NPOINTS
231  ipoint1=rpoints(ipoint2)
232  IF(ipoint1.GT.0) THEN
233  x1=grid1%X(1,ipoint1)
234  x2=grid2%X(1,ipoint2)*fscl
235  y1=grid1%X(2,ipoint1)
236  y2=grid2%X(2,ipoint2)*fscl
237  dlp=(x1-x2)**2+(y1-y2)**2
238  dlt=abs(x2-x1)*(abs(x1)+abs(x2)+eps)+
239  + abs(y2-y1)*(abs(y1)+abs(y2)+eps)
240  dlt=2.*tol*(dlt+eps)
241  IF(dlp.GT.dlt) THEN
242  ierr=400
243  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
244  w "internal error"
245  WRITE(gridman_unit,*)
246  w "points marked as overlapped are not same, "
247  WRITE(gridman_unit,*)
248  w " IPOINT1, IPOINT2, DLP, DLT, TOL",
249  w ipoint1, ipoint2, dlp, dlt, tol
250  WRITE(gridman_unit,*) " X1, Y1 ",x1,y1
251  WRITE(gridman_unit,*) " X2, Y2 ",x2,y2
252  RETURN
253  END IF
254  END IF
255  END DO
256 
257 C CHECK THAT INTERSECTIONS COVER THE WHOLE EDGES
258  DO iedge1=1,grid1%NEDGES
259  IF(.NOT.medge1(iedge1)) THEN
260  ipoint=grid1%POINTS(1,iedge1)
261  x1=grid1%X(1,ipoint)
262  y1=grid1%X(2,ipoint)
263  ipoint=grid1%POINTS(2,iedge1)
264  x2=grid1%X(1,ipoint)
265  y2=grid1%X(2,ipoint)
266  dlp=(x1-x2)**2+(y1-y2)**2
267  dlq=le1(iedge1)**2
268  dlt=abs(x2-x1)*(abs(x1)+abs(x2)+eps)+
269  + abs(y2-y1)*(abs(y1)+abs(y2)+eps)
270  dlt=4.*tol*(dlt+eps)
271 C IF LENGTH OF THE INTERSECTION IS NOT EQUAL TO THE LENGTH OF THE EDGE THEN ERROR
272  IF(abs(dlp-dlq).GT.dlt) GOTO 30
273  END IF
274  END DO
275 
276  DO iedge2=1,grid2%NEDGES
277  IF(.NOT.medge2(iedge2)) THEN
278  ipoint=grid2%POINTS(1,iedge2)
279  x1=grid2%X(1,ipoint)*fscl
280  y1=grid2%X(2,ipoint)*fscl
281  ipoint=grid2%POINTS(2,iedge2)
282  x2=grid2%X(1,ipoint)*fscl
283  y2=grid2%X(2,ipoint)*fscl
284  dlp=(x1-x2)**2+(y1-y2)**2
285  dlq=le2(iedge2)**2
286  dlt=abs(x2-x1)*(abs(x1)+abs(x2)+eps)+
287  + abs(y2-y1)*(abs(y1)+abs(y2)+eps)
288  dlt=4.*tol*(dlt+eps)
289 C IF LENGTH OF THE INTERSECTION IS NOT EQUAL TO THE LENGTH OF THE EDGE THEN ERROR
290  IF(abs(dlp-dlq).GT.dlt) GOTO 30
291  END IF
292  END DO
293 
294  GOTO 31
295  30 ierr=400
296  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
297  w "internal error"
298  WRITE(gridman_unit,*)
299  w " Intersection does not cover the whole edge."
300  WRITE(gridman_unit,*)
301  w " Unfortunately, current version can not ",
302  w " treat this situation properly."
303  WRITE(gridman_unit,*) " DLP, DLQ, DLT, TOL ",dlp,dlq,dlt,tol
304  RETURN
305  31 CONTINUE
306 
307 C ADD NON-BOUNDARY EDGES OF GRID1
308  lmap0=0
309  nedges0=nedges
310  DO iedge1=1,grid1%NEDGES
311  IF(medge1(iedge1)) THEN
312  nedges0=nedges0+1
313 C EDGE INDEX OF THE COMBINED GRID AS FUNCTION OF THE EDGE INDEX OF GRID1
314 C THIS TABLE IS REQUIRED TO RE-CALCULATE EDGE INDICES FOR TELEPORTATION
315  lmap0(iedge1)=nedges0
316  END IF
317  END DO
318 
319  DO iedge1=1,grid1%NEDGES
320  IF(medge1(iedge1)) THEN
321  nedges=nedges+1
322  IF(grid1%CELLS(1,iedge1).GE.0) THEN
323  cells(1,nedges)=grid1%CELLS(1,iedge1)
324  ELSE IF(grid1%CELLS(1,iedge1).LT.0) THEN
325 C PRESERVING INDEX FOR TELEPORTATION
326  iedge=-grid1%CELLS(1,iedge1)
327  IF(iedge.GT.grid1%NEDGES) GOTO 200
328  IF(iedge.GT.0) cells(1,nedges)=-lmap0(iedge)
329  END IF
330  IF(grid1%CELLS(2,iedge1).GE.0) THEN
331  cells(2,nedges)=grid1%CELLS(2,iedge1)
332  ELSE IF(grid1%CELLS(2,iedge1).LT.0) THEN
333 C PRESERVING INDEX FOR TELEPORTATION
334  iedge=-grid1%CELLS(2,iedge1)
335  IF(iedge.GT.grid1%NEDGES) GOTO 200
336  cells(2,nedges)=-lmap0(iedge)
337  END IF
338  points(1,nedges)=grid1%POINTS(1,iedge1)
339  points(2,nedges)=grid1%POINTS(2,iedge1)
340  imape1(1,nedges)=iedge1
341  imape1(2,nedges)=nedges
342  END IF
343  END DO
344 
345 C ADD NON-BOUNDARY EDGES OF GRID2, CONVERT INDICES OF POINTS
346  lmap0=0
347  nedges0=nedges
348  DO iedge2=1,grid2%NEDGES
349  IF(medge2(iedge2)) THEN
350  nedges0=nedges0+1
351 C EDGE INDEX OF THE COMBINED GRID AS FUNCTION OF THE EDGE INDEX OF GRID1
352 C THIS TABLE IS REQUIRED TO RE-CALCULATE EDGE INDICES FOR TELEPORTATION
353  lmap0(iedge2)=nedges0
354  END IF
355  END DO
356 
357  npoints=grid1%NPOINTS
358  nedges0=nedges
359  ncells=grid1%NCELLS
360  DO iedge2=1,grid2%NEDGES
361  IF(medge2(iedge2)) THEN
362  nedges=nedges+1
363  IF(grid2%CELLS(1,iedge2).GT.0) THEN
364  cells(1,nedges)=grid2%CELLS(1,iedge2)+ncells
365  ELSE IF(grid2%CELLS(1,iedge2).LT.0) THEN
366 C PRESERVING INDEX FOR TELEPORTATION
367  iedge=-grid2%CELLS(1,iedge2)
368  IF(iedge.GT.grid2%NEDGES) GOTO 300
369  cells(1,nedges)=-lmap0(iedge)
370  ELSE
371  cells(1,nedges)=0
372  END IF
373  IF(grid2%CELLS(2,iedge2).GT.0) THEN
374  cells(2,nedges)=grid2%CELLS(2,iedge2)+ncells
375  ELSE IF(grid2%CELLS(2,iedge2).LT.0) THEN
376 C INDEX FOR TELEPORTATION
377  iedge=-grid2%CELLS(2,iedge2)
378  IF(iedge.GT.grid2%NEDGES) GOTO 300
379  cells(2,nedges)=-lmap0(iedge)
380  ELSE
381  cells(2,nedges)=0
382  END IF
383  ipoint=grid2%POINTS(1,iedge2)
384  IF(rpoints(ipoint).GT.0) THEN
385 C THE POINT WAS REPLACED BY A POINT FROM GRID1
386  points(1,nedges)=rpoints(ipoint)
387  ELSE
388 C NO REPLACEMENT, JUST SHIFT
389  points(1,nedges)=ipoint+npoints
390  END IF
391  ipoint=grid2%POINTS(2,iedge2)
392  IF(rpoints(ipoint).GT.0) THEN
393  points(2,nedges)=rpoints(ipoint)
394  ELSE
395  points(2,nedges)=ipoint+npoints
396  END IF
397  imape2(1,nedges)=iedge2
398  imape2(2,nedges)=nedges
399  END IF
400  END DO
401 
402 C SHIFT POINT INDICES (TO SKIP REPLACED POINTS)
403  npoints=grid1%NPOINTS
404  mapp=0
405  DO ipoint=1,grid2%NPOINTS
406  IF(rpoints(ipoint).GT.0) cycle
407 C ADD ONLY POINTS WHICH WERE NOT REPLACED
408  npoints=npoints+1
409  mapp(ipoint)=npoints
410  END DO
411 
412 C CORRECT POINT INDICES
413  npoints1=grid1%NPOINTS
414  DO iedge=1,nedges
415  ipoint=points(1,iedge)
416  IF(ipoint.GT.npoints1) THEN
417  IF(mapp(ipoint-npoints1).GT.0) THEN
418  points(1,iedge)=mapp(ipoint-npoints1)
419  ELSE
420  GOTO 50
421  END IF
422  END IF
423  ipoint=points(2,iedge)
424  IF(ipoint.GT.npoints1) THEN
425  IF(mapp(ipoint-npoints1).GT.0) THEN
426  points(2,iedge)=mapp(ipoint-npoints1)
427  ELSE
428  GOTO 50
429  END IF
430  END IF
431  END DO
432  GOTO 51
433  50 ierr=400
434  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
435  w "internal error"
436  WRITE(gridman_unit,*) "no shift information for a point, ",
437  w " IEDGE, IPOINT ",iedge, ipoint
438  RETURN
439  51 CONTINUE
440 
441 C ALLOCATE NEW GRID
442  ncells=grid1%NCELLS+grid2%NCELLS
443  nedgeindex=grid1%NEDGEINDEX+grid2%NEDGEINDEX
444  ncellindex=grid1%NCELLINDEX+grid2%NCELLINDEX
445  CALL gridman_grid_allocate(grid,2,nedges,npoints,ncells,ierr,
446  c nedgeindex,ncellindex)
447  IF(ierr.GT.0) GOTO 400
448 
449 C COPY EDGES AND POINTS
450  grid%CELLS(1,1:nedges)=cells(1,1:nedges)
451  grid%CELLS(2,1:nedges)=cells(2,1:nedges)
452  grid%POINTS(1,1:nedges)=points(1,1:nedges)
453  grid%POINTS(2,1:nedges)=points(2,1:nedges)
454  DO ipoint=1,grid1%NPOINTS
455  grid%X(1,ipoint)=grid1%X(1,ipoint)
456  grid%X(2,ipoint)=grid1%X(2,ipoint)
457  END DO
458  DO ipoint=1,grid2%NPOINTS
459  IF(mapp(ipoint).GT.0) THEN
460  grid%X(1,mapp(ipoint))=grid2%X(1,ipoint)*fscl
461  grid%X(2,mapp(ipoint))=grid2%X(2,ipoint)*fscl
462  END IF
463  END DO
464  grid%UNIT2SI=grid1%UNIT2SI !TAKE UNITS OF GRID1
465  grid%UNITS=grid1%UNITS
466  grid%DESCRIPTION=trim(grid1%DESCRIPTION)//' <merged with> '//
467  / trim(grid2%DESCRIPTION)
468 
469  DO ii=1,grid1%NEDGEINDEX
470  CALL gridman_index_transform(grid%EDGEINDEX(ii),
471  c grid1%EDGEINDEX(ii),imape1,nedges,ierr)
472  IF(ierr.NE.0) GOTO 410
473  END DO
474  DO ii2=1,grid2%NEDGEINDEX
475  ii=ii2+grid1%NEDGEINDEX
476  CALL gridman_index_transform(grid%EDGEINDEX(ii),
477  c grid2%EDGEINDEX(ii2),imape2,nedges,ierr)
478  IF(ierr.NE.0) GOTO 420
479  END DO
480  DO ii=1,grid1%NCELLINDEX
481  CALL gridman_index_copy(grid%CELLINDEX(ii),
482  c grid1%CELLINDEX(ii),ierr)
483  IF(ierr.NE.0) GOTO 430
484  END DO
485  DO ii2=1,grid2%NCELLINDEX
486  ii=ii2+grid1%NCELLINDEX
487  CALL gridman_index_copy(grid%CELLINDEX(ii),
488  c grid2%CELLINDEX(ii2),ierr)
489  grid%CELLINDEX(ii)%INDEXES(0,:)=grid%CELLINDEX(ii)%INDEXES(0,:)+
490  + grid1%NCELLS
491  IF(ierr.NE.0) GOTO 440
492  END DO
493 
494  CALL gridman_grid2d_check(grid,res,ierr)
495  IF(res.NE.0.OR.ierr.GT.0) GOTO 100
496 
497  IF(gridman_dbg)
498  w WRITE(gridman_unit,*) "GRIDMAN_GRID2D_MERGE finished"
499 
500  RETURN
501 
502  100 ierr=400
503  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
504  w "internal error - wrong resulting GRID"
505  WRITE(gridman_unit,*) " RES ",res
506  RETURN
507 
508  200 ierr=100
509  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
510  w "index for teleportation on GRID1 is out of range"
511  WRITE(gridman_unit,*) " IEDGE1, IEDGE ",iedge1, iedge
512  RETURN
513 
514  300 ierr=100
515  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
516  w "index for teleportation on GRID2 is out of range"
517  WRITE(gridman_unit,*) " IEDGE2, IEDGE ",iedge1, iedge
518  RETURN
519 
520  400 WRITE(gridman_unit,*) "GRIDMAN_GRID2D_MERGE terminated"
521  RETURN
522 
523  410 ierr=420
524  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
525  w "cannot create edge index II1 ",ii
526  RETURN
527  420 ierr=420
528  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
529  w "cannot create edge index II2 ",ii2
530  RETURN
531  430 ierr=430
532  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
533  w "cannot create cell index II1 ",ii
534  RETURN
535  440 ierr=440
536  WRITE(gridman_unit,*) "ERROR in GRIDMAN_GRID2D_MERGE: ",
537  w "cannot create cell index II2 ",ii2
538  RETURN
539 
540  CONTAINS
541 
542 C
543 C FIND INTERSECTION OF TWO EDGES: OVERLAP AND "HANGING" EDGES
544 C
545 C THIS SUBROUTINE LOOKS SO STRANGE BECAUSE ORIGINALY I WANTED TO
546 C WRITE A GENERAL ALGORITHM WHICH CAN ALSO PROCESS "HANGING TAILS"
547 C OF THE INTERSECTIONS
548 C
549  SUBROUTINE find_overlap(P,Q,XP,YP,XQ,YQ,TOL,IND,TPQ)
550  IMPLICIT NONE
551  INTRINSIC abs,tiny
552 
553  INTEGER(GRIDMAN_SP),INTENT(IN) :: P(2),Q(2) !INDICES OF POINTS OF P AND Q EDGES
554  REAL(GRIDMAN_DP),INTENT(IN) :: XP(2),YP(2), !COORDINATES OF THE P AND Q EDGES
555  r xq(2),yq(2)
556  REAL(GRIDMAN_DP),INTENT(IN) :: TOL !ACCURACY OF GEOMETRICAL OPERATIONS
557  INTEGER(GRIDMAN_SP),INTENT(OUT) :: IND(6), !SEQUENCE OF INDICES IN RESULTING INTERSECTION
558  i tpq(2,2) !INDEX P WHICH CORRESPONDS TO Q IF REPLACED
559 
560  REAL(GRIDMAN_DP) :: T,DEL,ZP1,ZP2,ZQ1,ZQ2,EPS
561  INTEGER(GRIDMAN_SP) :: P1,P2,Q1,Q2
562  INTEGER(GRIDMAN_SP),PARAMETER :: NULL=0
563  eps=10.*tiny(eps) !MACHINE PRECISION
564 
565  tpq=0
566 C POINT Q(1)
567  del=abs(yp(2)-yp(1))*(abs(xq(1))+abs(xp(1))+eps)+
568  + abs(xq(1)-xp(1))*(abs(yp(2))+abs(yp(1))+eps)+
569  + abs(xp(2)-xp(1))*(abs(yq(1))+abs(yp(1))+eps)+
570  + abs(yq(1)-yp(1))*(abs(xp(2))+abs(xp(1))+eps)
571  del=tol*(del+eps)
572  t=(xq(1)-xp(1))*(yp(2)-yp(1))
573  t=t-(yq(1)-yp(1))*(xp(2)-xp(1))
574 C DEL IS THE ESTIMATE OF THE ERROR OF T CALCULATED
575 C ON ASSUMPTION THAT RELATIVE ERRORS OF ALL X, Y
576 C ARE EQUAL TO TOL
577  IF(abs(t).GT.del) THEN
578 C POINT Q(1) DOES NOT LIE ON THE LINE P, RETURN
579  ind=0
580  RETURN
581  END IF
582 
583 C POINT Q(2)
584  del=abs(yp(2)-yp(1))*(abs(xq(2))+abs(xp(1)))+
585  + abs(xq(2)-xp(1))*(abs(yp(2))+abs(yp(1)))+
586  + abs(xp(2)-xp(1))*(abs(yq(2))+abs(yp(1)))+
587  + abs(yq(2)-yp(1))*(abs(xp(2))+abs(xp(1)))
588  del=tol*del
589  t=(xq(2)-xp(1))*(yp(2)-yp(1))
590  t=t-(yq(2)-yp(1))*(xp(2)-xp(1))
591  IF(abs(t).GT.del) THEN
592 C POINT Q(2) DOES NOT LIE ON THE LINE P, RETURN
593  ind=0
594  RETURN
595  END IF
596 
597  IF(abs(xp(2)-xp(1)).GT.abs(yp(2)-yp(1))) THEN
598 C X PROJECTION OF THE INTERVAL P IS LARGER
599 C USE X COORDINATE TO ARRANGE POINTS
600  IF(xp(2).GT.xp(1)) THEN
601 C PRESCRIBED ORDER
602  zp1=xp(1)
603  zp2=xp(2)
604  p1=p(1)
605  p2=p(2)
606  ELSE
607 C INVERSE ORDER
608  zp1=xp(2)
609  zp2=xp(1)
610  p1=p(2)
611  p2=p(1)
612  END IF
613  IF(xq(2).GT.xq(1)) THEN
614 C PRESCRIBED ORDER
615  zq1=xq(1)
616  zq2=xq(2)
617  q1=q(1)
618  q2=q(2)
619  ELSE
620 C INVERSE ORDER
621  zq1=xq(2)
622  zq2=xq(1)
623  q1=q(2)
624  q2=q(1)
625  END IF
626  ELSE
627 C Y PROJECTION OF THE INTERVAL P IS LARGER
628 C USE Y COORDINATE TO ARRANGE POINTS
629  IF(yp(2).GT.yp(1)) THEN
630 C PRESCRIBED ORDER
631  zp1=yp(1)
632  zp2=yp(2)
633  p1=p(1)
634  p2=p(2)
635  ELSE
636 C INVERSE ORDER
637  zp1=yp(2)
638  zp2=yp(1)
639  p1=p(2)
640  p2=p(1)
641  END IF
642  IF(yq(2).GT.yq(1)) THEN
643 C PRESCRIBED ORDER
644  zq1=yq(1)
645  zq2=yq(2)
646  q1=q(1)
647  q2=q(2)
648  ELSE
649 C INVERSE ORDER
650  zq1=yq(2)
651  zq2=yq(1)
652  q1=q(2)
653  q2=q(1)
654  END IF
655  END IF
656 
657  IF(abs(zq1-zp1).LT.tol*(abs(zq1)+abs(zp1)+eps).AND.
658  f abs(zq2-zp2).LT.tol*(abs(zq2)+abs(zp2)+eps)) THEN
659  ind=(/null,null,p1,p2,null,null/) !1
660  tpq(1,:)=(/q1,q2/)
661  tpq(2,:)=(/p1,p2/)
662  ELSE IF(abs(zq1-zp1).LT.tol*(abs(zq1)+abs(zp1)+eps)) THEN
663  IF(zq2.GT.zp2) THEN
664  ind=(/null,null,p1,p2,p2,q2/) !2
665  ELSE
666  ind=(/null,null,p1,q2,q2,p1/) !3
667  END IF
668  tpq(1,1)=q1
669  tpq(2,1)=p1
670  ELSE IF(abs(zq2-zp2).LT.tol*(abs(zq2)+abs(zp2)+eps)) THEN
671  IF(zq1.LT.zp1) THEN
672  ind=(/q1,p1,p1,p2,null,null/) !4
673  ELSE
674  ind=(/p1,q1,q1,p2,null,null/) !5
675  END IF
676  tpq(1,1)=q2
677  tpq(2,1)=p2
678  ELSE IF(abs(zq2-zp1).LT.tol*(abs(zq2)+abs(zp1)+eps)) THEN
679  ind=(/q1,p1,p1,null,p1,p2/) !6
680  tpq(1,1)=q2
681  tpq(2,1)=p1
682  ELSE IF(abs(zq1-zp2).LT.tol*(abs(zq1)+abs(zp2)+eps)) THEN
683  ind=(/p1,p2,null,p2,p2,q2/) !7
684  tpq(1,1)=q1
685  tpq(2,1)=p2
686  ELSE IF(zq1.LT.zp1) THEN
687  IF(zq2.LT.zp1) THEN
688  ind=(/q1,q2,null,null,p1,p2/) !8
689  ELSE IF(zq2.GT.zp2) THEN
690  ind=(/q1,p1,p1,p2,p2,q2/) !9
691  ELSE
692  ind=(/q1,p1,p1,q2,q2,p1/) !10
693  END IF
694  ELSE IF(zq1.GT.zp2) THEN
695  ind=(/p1,p2,null,null,q1,q2/) !11
696  ELSE ! ZP1<ZQ1<ZP2
697  IF(zq2.LT.zp2) THEN
698  ind=(/p1,q1,q1,q2,q2,p2/) !12
699  ELSE
700  ind=(/p1,q1,q1,p2,p2,q2/) !13
701  END IF
702  END IF
703 
704  END SUBROUTINE find_overlap
705 
706 C
707 C RETURN ONE OF TWO CELLS WHICH IS LARGER THAN 0
708 C IF BOTH LE 0 THEN RETURNS 0
709 C
710  FUNCTION nonzer_cell(CELLS)
711  INTEGER(GRIDMAN_SP),INTENT(IN) :: CELLS(2)
712  INTEGER(GRIDMAN_SP) :: NONZER_CELL
713  IF(cells(1).GT.0) THEN
714  nonzer_cell=cells(1)
715  ELSE IF(cells(2).GT.0) THEN
716  nonzer_cell=cells(2)
717  ELSE
718  nonzer_cell=0
719  END IF
720  END FUNCTION nonzer_cell
721 
722  END SUBROUTINE gridman_grid2d_merge
subroutine gridman_grid2d_merge(GRID, GRID1, GRID2, TOL, IERR)
Merge two 2D grids by connecting their boundary edges.
Definition: merge.f:39
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_index_copy(INDEX2, INDEX1, IERR)
Create a copy of the index object.
Definition: index.f:538
subroutine gridman_grid2d_check(GRID, RES, IERR)
Check correctness of the 2D grid object.
Definition: grid2d.f:37
subroutine gridman_index_transform(INDEX2, INDEX1, IMAP12, N12, IERR)
Transform indices of elements - IND(0,:)
Definition: index.f:788
Data-type which describes a grid as a set of edges, methods in grid.f.
Definition: gridman.f:168
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