Choral
mesh_tools.f90
Go to the documentation of this file.
1 
8 
9 
10 module mesh_tools
11 
14  use real_type
15  use basic_tools
16  use algebra_set, only: cap_sorted_set
17  use graph_mod
18  use cell_mod
19  use mesh_mod
20 
21  implicit none
22  private
23 
24  public :: mesh_analyse !! TESTED
25  public :: maxedgelength, minedgelength
26 
27 contains
28 
33  function maxedgelength(m) result(h)
34  type(mesh), intent(in) :: m
35  real(RP) :: h
36 
37  integer, dimension(:), allocatable :: row
38  real(RP), dimension(3) :: x
39  integer :: ii, sz, wdt
40  real(RP) :: l
41 
42  h = 0._rp
43  wdt = m%clToNd%width
44  call allocmem(row, wdt)
45 
46  do ii=1, m%nbCl
47 
48  call getrow(sz, row, wdt, m%clToNd, ii)
49 
50  select case(m%clType(ii))
51  case(cell_vtx)
52  cycle
53 
54  case(cell_edg, cell_edg_2) ! indicqtive if order = 2
55  x = m%nd(:,row(1)) - m%nd(:,row(2))
56  l = sqrt(sum(x*x))
57  if (l>h) h=l
58 
59 
60  case(cell_trg, cell_trg_2) ! indicqtive if order = 2
61  x = m%nd(:,row(1)) - m%nd(:,row(2))
62  l = sqrt(sum(x*x))
63  if (l>h) h=l
64 
65  x = m%nd(:,row(2)) - m%nd(:,row(3))
66  l = sqrt(sum(x*x))
67  if (l>h) h=l
68 
69  x = m%nd(:,row(3)) - m%nd(:,row(1))
70  l = sqrt(sum(x*x))
71  if (l>h) h=l
72 
73  case(cell_tet, cell_tet_2)
74  x = m%nd(:,row(1)) - m%nd(:,row(2))
75  l = sqrt(sum(x*x))
76  if (l>h) h=l
77 
78  x = m%nd(:,row(1)) - m%nd(:,row(3))
79  l = sqrt(sum(x*x))
80  if (l>h) h=l
81 
82  x = m%nd(:,row(1)) - m%nd(:,row(4))
83  l = sqrt(sum(x*x))
84  if (l>h) h=l
85 
86  x = m%nd(:,row(2)) - m%nd(:,row(3))
87  l = sqrt(sum(x*x))
88  if (l>h) h=l
89 
90  x = m%nd(:,row(2)) - m%nd(:,row(4))
91  l = sqrt(sum(x*x))
92  if (l>h) h=l
93 
94  x = m%nd(:,row(3)) - m%nd(:,row(4))
95  l = sqrt(sum(x*x))
96  if (l>h) h=l
97 
98  case default
99  call quit ("mesh_tools: maxEdgeLength:&
100  & cell type not supported")
101 
102  end select
103  end do
104 
105  end function maxedgelength
106 
109  function minedgelength(m) result(h)
110  type(mesh), intent(in) :: m
111  real(RP) :: h
112 
113  integer, dimension(:), allocatable :: row
114  real(RP), dimension(3) :: x
115  integer :: ii, sz, wdt
116  real(RP) :: l
117 
118  h = 1e10_rp
119  wdt = m%clToNd%width
120  call allocmem(row, wdt)
121 
122  do ii=1, m%nbCl
123 
124  call getrow(sz, row, wdt, m%clToNd, ii)
125 
126  select case(m%clType(ii))
127  case(cell_vtx)
128  cycle
129 
130  case(cell_edg, cell_edg_2) ! indicqtive if order = 2
131  x = m%nd(:,row(1)) - m%nd(:,row(2))
132  l = sqrt(sum(x*x))
133  if (l<h) h=l
134 
135  case(cell_trg, cell_trg_2) ! indicqtive if order = 2
136  x = m%nd(:,row(1)) - m%nd(:,row(2))
137  l = sqrt(sum(x*x))
138  if (l<h) h=l
139 
140  x = m%nd(:,row(2)) - m%nd(:,row(3))
141  l = sqrt(sum(x*x))
142  if (l<h) h=l
143 
144  x = m%nd(:,row(3)) - m%nd(:,row(1))
145  l = sqrt(sum(x*x))
146  if (l<h) h=l
147 
148  case(cell_tet, cell_tet_2)
149  x = m%nd(:,row(1)) - m%nd(:,row(2))
150  l = sqrt(sum(x*x))
151  if (l<h) h=l
152 
153  x = m%nd(:,row(1)) - m%nd(:,row(3))
154  l = sqrt(sum(x*x))
155  if (l<h) h=l
156 
157  x = m%nd(:,row(1)) - m%nd(:,row(4))
158  l = sqrt(sum(x*x))
159  if (l<h) h=l
160 
161  x = m%nd(:,row(2)) - m%nd(:,row(3))
162  l = sqrt(sum(x*x))
163  if (l<h) h=l
164 
165  x = m%nd(:,row(2)) - m%nd(:,row(4))
166  l = sqrt(sum(x*x))
167  if (l<h) h=l
168 
169  x = m%nd(:,row(3)) - m%nd(:,row(4))
170  l = sqrt(sum(x*x))
171  if (l<h) h=l
172 
173  case default
174  call quit ("mesh_tools: minEdgeLength:&
175  & cell type not supported")
176 
177  end select
178  end do
179 
180  end function minedgelength
181 
182 
199  function mesh_analyse(m, verb) result(mesh_desc)
200  integer , dimension(4,6) :: mesh_desc
201  type(mesh), intent(in) :: m
202  integer , intent(in) :: verb
203 
204  integer :: ii, cl_t, dim, nbVtx, nbNodes
205  integer, dimension(CELL_MAX_NBNODES) :: row
206  integer, dimension(4, m%nbNd) :: p, q
207 
208  if (choral_verb>0) write(*,*) "mesh_tools : mesh_analyse"
209  mesh_desc = 0
210 
211 
212  if(.NOT.valid(m)) then
213  call quit( "mesh_tools: mesh_analyse: mesh 'm' not valid" )
214  end if
215 
216  p = 0; q = 0
217  do ii=1, m%nbCl
218 
219  cl_t = m%clType(ii)
220  dim = cell_dim(cl_t)
221  nbvtx = cell_nbvtx(cl_t)
222 
223  mesh_desc( dim + 1, 1) = mesh_desc( dim + 1, 1) + 1
224 
225  call getrow(nbnodes, row, cell_max_nbnodes, m%clToNd, ii)
226  p(dim + 1, row(1:nbvtx )) = 1
227  q(dim + 1, row(1:nbnodes )) = 1
228 
229  end do
230 
231  do ii=1, 4
232  mesh_desc(ii,2) = sum( p(ii,:) )
233  mesh_desc(ii,3) = sum( q(ii,:) )
234  end do
235 
236  mesh_desc(2,6) = mesh_desc(2,1) - mesh_desc(2,2)
237  if (m%dim==1) goto 10
238 
239  mesh_desc(3,4) = count_2dcell_edges(m)
240  mesh_desc(3,6) = mesh_desc(3,1) - mesh_desc(3,4) + mesh_desc(3,2)
241  if (m%dim==2) goto 10
242 
243  mesh_desc(4,4) = count_3dcell_edges(m)
244  mesh_desc(4,5) = count_3dcell_faces(m)
245  mesh_desc(4,6) = mesh_desc(4,1) - mesh_desc(4,5) &
246  & + mesh_desc(4,4) - mesh_desc(4,2)
247 
248 10 continue
249 
250  if (verb>0) call display_mesh_desc()
251 
252  if (mesh_desc(1,1)/=mesh_desc(1,2)) call quit( &
253  & "mesh_tools: mesh_analyse: 2" )
254 
255  if (mesh_desc(1,1)/=mesh_desc(1,3)) call quit( &
256  & "mesh_tools: mesh_analyse: 3" )
257 
258  contains
259 
260  subroutine display_mesh_desc()
262  call print(m)
263  write(*,*)" 0D cells"
264  write(*,*)" nb cells =", mesh_desc(1,1)
265  write(*,*)" nb vertexes =", mesh_desc(1,2)
266  write(*,*)" nb nodes =", mesh_desc(1,3)
267 
268  write(*,*)" 1D cells"
269  write(*,*)" nb cells =", mesh_desc(2,1)
270  write(*,*)" nb vertexes =", mesh_desc(2,2)
271  write(*,*)" Euler charac =", mesh_desc(2,6)
272  write(*,*)" nb nodes =", mesh_desc(2,3)
273  if (m%dim==1) return
274 
275  write(*,*)" 2D cells"
276  write(*,*)" nb cells =", mesh_desc(3,1)
277  write(*,*)" nb edges =", mesh_desc(3,4)
278  write(*,*)" nb vertexes =", mesh_desc(3,2)
279  write(*,*)" Euler charac =", mesh_desc(3,6)
280  write(*,*)" nb nodes =", mesh_desc(3,3)
281  if (m%dim==2) return
282 
283  write(*,*)" 3D cells"
284  write(*,*)" nb cells =", mesh_desc(4,1)
285  write(*,*)" nb faces =", mesh_desc(4,5)
286  write(*,*)" nb edges =", mesh_desc(4,4)
287  write(*,*)" nb vertexes =", mesh_desc(4,2)
288  write(*,*)" Euler charac =", mesh_desc(4,6)
289  write(*,*)" nb nodes =", mesh_desc(4,2)
290 
291  end subroutine display_mesh_desc
292 
293  end function mesh_analyse
294 
297  function count_3dcell_edges(m) result(nEd)
298  type(mesh), intent(in) :: m
299  integer :: nEd
300 
301  integer :: wdt
302 
303  ned = 0
304 
305  if (m%dim/=3) return
306 
307  ! Maximal number of neiuhbour cells
308  ! of the nodes of the mesh
309  !
310  wdt = m%ndToCl%width
311 
312  call cell_loop()
313 
314  contains
315 
316  subroutine cell_loop()
317 
318  integer, dimension(wdt, CELL_MAX_NBVTX):: vtx_toCl
319  integer, dimension(CELL_MAX_NBVTX) :: vtx_nbCl
320  integer, dimension(CELL_MAX_NBNODES) :: cl_vtx
321  integer, dimension(wdt) :: ed_toCl
322 
323  integer :: ii, jj, ll, v1, v2
324  integer :: cl, cl_nbVtx, cl_t
325  integer :: ed_nbCl, cl2, cl2_t
326 
327  do cl=1, m%nbCl
328 
329  cl_t = m%clType(cl)
330  if ( cell_dim(cl_t) /= 3 ) cycle
331 
332  !! cl_nbVtx = number of vertexes of cell cl
333  !! cl_vtx(:) = vertexes of cl (global indexzs)
334  !!
335  call getrow(ii, cl_vtx, cell_max_nbnodes, &
336  & m%clToNd, cl)
337  cl_nbvtx = cell_nbvtx( cl_t )
338 
339  !! For the vertex ii of cell cl :
340  !! vtx_nbCl(ii) = number of neighbour cells
341  !! vtx_toCl(:,ii) = neighbour cells
342  !!
343  do ii=1, cl_nbvtx
344  call getrow(vtx_nbcl(ii), vtx_tocl(:,ii), wdt, &
345  & m%ndToCl, cl_vtx(ii))
346  end do
347 
348  ! Loop on cell cl edges
349  do ii=1, cell_nbed(cl_t)
350 
351  !! edge ii vertexes = local indexing
352  !! in the cell cl
353  v1 = cell_ed_vtx(1, ii, cl_t)
354  v2 = cell_ed_vtx(2, ii, cl_t)
355 
356 
357  ! Neighbour cells to the edge ii
358  !
359  jj = vtx_nbcl(v1)
360  ll = vtx_nbcl(v2)
361  call cap_sorted_set(ed_nbcl, ed_tocl, wdt, &
362  & vtx_tocl( 1: jj, v1), jj, &
363  & vtx_tocl( 1: ll, v2), ll )
364 
365  ! Test if that edge is a new face
366  !
367  loop: do jj=1, ed_nbcl
368  cl2 = ed_tocl(jj)
369  cl2_t = m%clType(cl2)
370  if (cell_dim(cl2_t)==3) exit loop
371  end do loop
372  if (cl2==cl) ned = ned + 1 ! new edge
373 
374  end do
375  end do
376  end subroutine cell_loop
377 
378  end function count_3dcell_edges
379 
380 
381 
384  function count_2dcell_edges(m) result(n)
385  integer :: n
386  type(mesh), intent(in) :: m
387 
388  integer, dimension(:), allocatable :: nnz
389  type(graph) :: clToEd
390 
391  integer :: cl
392  integer :: cl_t, nb_vtx, nb_ed, width
393 
394  if (choral_verb>1) write(*,*) &
395  & "mesh_tools : count_2DCell_edges"
396 
397  !! STEP 1: build clToEd pattern
398  !!
399  call allocmem(nnz, m%nbCl)
400  do cl=1, m%nbCl
401  cl_t = m%clType(cl)
402  if ( cell_dim(cl_t) ==2 ) then
403  nnz(cl) = cell_nbed(cl_t)
404  else
405  nnz(cl) = 0
406  end if
407  end do
408  if (sum(nnz)==0) then
409  n = 0
410  return
411  end if
412  cltoed = graph(nnz, m%nbCl, 0)
413 
414 
415  !! STEP 2 : count edges
416  !!
417  n = 0
418  width = m%ndToCl%width
419  do cl_t=1, cell_tot_nb
420  if ( cell_dim(cl_t) /= 2 ) cycle
421  if ( m%cell_count(cl_t) == 0 ) cycle
422 
423  nb_vtx = cell_nbvtx(cl_t)
424  nb_ed = cell_nbed(cl_t)
425  call cell_loop()
426 
427  end do
428 
429  contains
430 
431  !! count the edges of the cells with type cl_t
432  !!
433  subroutine cell_loop()
434 
435  integer, dimension(nb_vtx) :: vtx_nbCl
436  integer, dimension(width, nb_vtx) :: vtx_cl
437  integer, dimension(CELL_MAX_NBVTX) :: cl_vtx
438  integer, dimension(width) :: coBord
439  integer :: ed, v1, v2
440  integer :: j1, j2, l1, l2
441 
442  do cl=1, m%nbCl
443  l1 = m%clType(cl)
444  if (l1 /= cl_t ) cycle
445 
446  !! cell cl vertexes
447  !!
448  j1 = m%clToNd%row(cl)
449  j2 = j1 + nb_vtx - 1
450  cl_vtx(1:nb_vtx) = m%clToNd%col( j1:j2 )
451 
452  !! neighbour cells for each vertex
453  !! of the cell cl
454  !!
455  do v1=1, nb_vtx
456  l1 = cl_vtx(v1)
457  j1 = m%ndToCl%row(l1)
458  j2 = m%ndToCl%row(l1+1)
459 
460  l1 = j2-j1
461  vtx_nbcl(v1) = l1
462 
463  !! vtx_cl is sorted !
464  vtx_cl(1:l1, v1) = m%ndToCl%col(j1:j2-1)
465 
466  end do
467 
468  !! get the co-boundary of the edges of cl
469  !! and update the total number of edges
470  !!
471  j1 = cltoed%row(cl)
472  do ed=1, nb_ed
473 
474  !! v1, v2 = vertexes of the current edge, local indexes
475  v1 = cell_ed_vtx(1, ed, cl_t)
476  v2 = cell_ed_vtx(2, ed, cl_t)
477 
478  !! list the cells sharing the vertexes v1 and v2
479  !! coBord is sorted !
480  l1 = vtx_nbcl(v1)
481  l2 = vtx_nbcl(v2)
482 
483  call cap_sorted_set(j2, cobord, width, &
484  & vtx_cl(1:l1, v1), l1, vtx_cl(1:l2, v2), l2)
485 
486  !! determine if the current edge is a new edge
487  !!
488  do l1=1, j2
489  if ( nnz( cobord(l1) ) == 0 ) cycle
490  exit
491  end do
492  if (cobord(l1)==cl) n = n + 1
493 
494  !! increment edge index
495  j1 = j1 + 1
496 
497  end do
498  end do
499 
500  end subroutine cell_loop
501 
502  end function count_2dcell_edges
503 
506  function count_3dcell_faces(m) result(n)
507  integer :: n
508  type(mesh), intent(in) :: m
509 
510  integer, dimension(:), allocatable :: nnz
511  type(graph) :: clToFc
512 
513  integer :: cl
514  integer :: cl_t, nb_vtx, nb_fc, width
515 
516  if (choral_verb>1) write(*,*) &
517  & "mesh_tools : count_3DCell_faces"
518 
519  !! STEP 1: build clToFc pattern
520  !!
521  call allocmem(nnz, m%nbCl)
522  do cl=1, m%nbCl
523  cl_t = m%clType(cl)
524  if ( cell_dim(cl_t) == 3 ) then
525  nnz(cl) = cell_nbfc(cl_t)
526  else
527  nnz(cl) = 0
528  end if
529  end do
530  cltofc = graph(nnz, m%nbCl, 0)
531 
532 
533  !! STEP 2 : count faces
534  !!
535  n = 0
536  width = m%ndToCl%width
537  do cl_t=1, cell_tot_nb
538  if ( cell_dim(cl_t) /= 3 ) cycle
539  if ( m%cell_count(cl_t) == 0 ) cycle
540 
541  nb_vtx = cell_nbvtx(cl_t)
542  nb_fc = cell_nbfc(cl_t)
543  call cell_loop()
544 
545  end do
546 
547  contains
548 
549  !! count the faces of the cells with type cl_t
550  !!
551  subroutine cell_loop()
552 
553  integer, dimension(nb_vtx) :: vtx_nbCl
554  integer, dimension(width, nb_vtx) :: vtx_cl
555  integer, dimension(CELL_MAX_NBVTX) :: cl_vtx
556  integer, dimension(width) :: coBord, aux
557  integer :: fc, v1, v2
558  integer :: j1, j2, l1, l2, ii
559 
560  do cl=1, m%nbCl
561  l1 = m%clType(cl)
562  if (l1 /= cl_t ) cycle
563 
564  !! cell cl vertexes
565  !!
566  j1 = m%clToNd%row(cl)
567  j2 = j1 + nb_vtx - 1
568  cl_vtx(1:nb_vtx) = m%clToNd%col( j1:j2 )
569 
570  !! neighbour cells for each vertex
571  !! of the cell cl
572  !!
573  do v1=1, nb_vtx
574  l1 = cl_vtx(v1)
575  j1 = m%ndToCl%row(l1)
576  j2 = m%ndToCl%row(l1+1)
577 
578  l1 = j2-j1
579  vtx_nbcl(v1) = l1
580 
581  !! vtx_cl is sorted !
582  vtx_cl(1:l1, v1) = m%ndToCl%col(j1:j2-1)
583 
584  end do
585 
586  !! get the co-boundary of the faces of cl
587  !! and update the total number of faces
588  !!
589  j1 = cltofc%row(cl)
590  do fc=1, nb_fc
591 
592  !! v1, v2 = vertexes of the current face, local indexes
593  v1 = cell_fc_vtx(1, fc, cl_t)
594  v2 = cell_fc_vtx(2, fc, cl_t)
595 
596  !! list the cells sharing the vertexes v1 and v2
597  !! coBord is sorted !
598  l1 = vtx_nbcl(v1)
599  l2 = vtx_nbcl(v2)
600 
601  call cap_sorted_set(j2, cobord, width, &
602  & vtx_cl(1:l1, v1), l1, vtx_cl(1:l2, v2), l2)
603 
604  do ii=3, cell_fc_nbvtx(fc, cl_t)
605  v2 = cell_fc_vtx(ii, fc, cl_t)
606  l2 = vtx_nbcl(v2)
607 
608  l1 = j2
609  aux(1:l1) = cobord(1:l1)
610 
611  call cap_sorted_set(j2, cobord(1:l1), l1, &
612  & aux(1:l1), l1, vtx_cl(1:l2, v2), l2)
613 
614  end do
615 
616  !! determine if the current face is a new face
617  !!
618  do l1=1, j2
619  if ( nnz( cobord(l1) ) == 0 ) cycle
620  exit
621  end do
622  if (cobord(l1)==cl) n = n + 1
623 
624  !! increment face index
625  j1 = j1 + 1
626 
627  end do
628  end do
629 
630  end subroutine cell_loop
631 
632  end function count_3dcell_faces
633 
634 
635 end module mesh_tools
Derived type mesh.
Definition: mesh_mod.F90:92
is the csr matrix well defined ?
Definition: csr_mod.F90:101
DERIVED TYPE graph: sparse matrices of boolean in CSR format
Definition: graph_mod.F90:33
integer, parameter cell_edg_2
Quadratic edge.
subroutine loop()
integer, parameter cell_tot_nb
Number of CELL types.
integer, parameter cell_tet
Tetrahedron.
BASIC TOOLS
Definition: basic_tools.F90:8
real(rp) function, public maxedgelength(m)
Returns the mesh size.
Definition: mesh_tools.f90:34
integer, dimension(cell_tot_nb), public cell_nbvtx
Number of vertexes for each cell type.
Definition: cell_mod.f90:118
real(rp) function, public minedgelength(m)
Returns the minimal edge length of the mesh.
Definition: mesh_tools.f90:110
integer function count_3dcell_faces(m)
count the faces of all 3D-cells
Definition: mesh_tools.f90:507
integer function count_3dcell_edges(m)
Counts the edges of the cells of dimension 3.
Definition: mesh_tools.f90:298
integer, dimension(cell_tot_nb), public cell_nbfc
Number of faces for each cell type.
Definition: cell_mod.f90:124
subroutine, public quit(message)
Stop program execution, display an error messahe.
integer, parameter cell_edg
Edge (line segment)
integer, dimension(cell_tot_nb), public cell_dim
Dimension for each cell type.
Definition: cell_mod.f90:130
integer, dimension(cell_max_nbvtx, cell_max_nbfc, cell_tot_nb), public cell_fc_vtx
CELL_FC_VTX(1:n, fc, cl) = vertexes for the face fc of the cell cl, with n = CELL_FC_NBVTX(fc, cl)
Definition: cell_mod.f90:146
REAL NUMBERS PRECISION IN CHORAL: selects simple/double/quad
Definition: real_type.F90:33
integer function, dimension(4, 6), public mesh_analyse(m, verb)
Analyse the cells in the mesh for every dimension.
Definition: mesh_tools.f90:200
integer, dimension(cell_max_nbfc, cell_tot_nb), public cell_fc_nbvtx
CELL_FC_NBVTX(fc, cl) = number of vertexes for the face fc of the cell cl.
Definition: cell_mod.f90:141
integer, parameter cell_trg
Triangle.
integer, parameter cell_tet_2
Quadratic tetrahedron.
CHORAL CONSTANTS
integer, parameter cell_trg_2
Quadratic triangle.
ALGEBRAIC OPERATIONS ON SETS
Definition: algebra_set.F90:14
integer, dimension(cell_tot_nb), public cell_nbed
Number of edges for each cell type.
Definition: cell_mod.f90:121
DERIVED TYPE mesh
Definition: mesh_mod.F90:57
allocate memory for real(RP) arrays
Definition: real_type.F90:158
subroutine display_mesh_desc()
Definition: mesh_tools.f90:261
integer choral_verb
Verbosity level.
DEFINITION OF GLOBAL VARIABLES FOR THE LIBRARY CHORAL
short description for real arrays
Definition: real_type.F90:141
subroutine cell_loop()
Definition: diffusion.F90:232
integer, parameter cell_vtx
Vertex.
subroutine, public cap_sorted_set(cpt, t, n, t1, n1, t2, n2)
t(1:cpt) = t1(1:n1) \cap t2(1:n2)
integer, dimension(2, cell_max_nbed, cell_tot_nb), public cell_ed_vtx
CELL_ED_VTX(1:2, ed, cl) = vertexes for the edge ed of the cell cl.
Definition: cell_mod.f90:137
The type graph stores sparse matrices of boolean in CSR format.
Definition: graph_mod.F90:78
TOOLS TO GET mesh INFORMATIONS
Definition: mesh_tools.f90:10
DEFINITION OF GEOMETRICAL CELLS (for meshes)
Definition: cell_mod.f90:82
integer function count_2dcell_edges(m)
count the edges of all 2D-cells
Definition: mesh_tools.f90:385
integer, parameter, public cell_max_nbnodes
Cell maximal number of nodes.