FV3 Bundle
type_mesh.F90
Go to the documentation of this file.
1 !----------------------------------------------------------------------
2 ! Module: type_mesh
3 ! Purpose: mesh derived type
4 ! Author: Benjamin Menetrier
5 ! Licensing: this code is distributed under the CeCILL-C license
6 ! Copyright © 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
7 !----------------------------------------------------------------------
8 module type_mesh
9 
10 !$ use omp_lib
11 use tools_const, only: req
13 use tools_kinds, only: kind_real
16 use type_mpl, only: mpl_type
17 use type_rng, only: rng_type
18 
19 implicit none
20 
21 logical,parameter :: shuffle = .true. ! Shuffle mesh order (more efficient to compute the Delaunay triangulation)
22 
23 ! Mesh derived type
25  ! Mesh structure
26  integer :: n ! Number of points
27  integer,allocatable :: order(:) ! Order of shuffled points
28  integer,allocatable :: order_inv(:) ! Inverse order of shuffled points
29  real(kind_real),allocatable :: lon(:) ! Points longitudes
30  real(kind_real),allocatable :: lat(:) ! Points latitudes
31  real(kind_real),allocatable :: x(:) ! x-coordinate
32  real(kind_real),allocatable :: y(:) ! y-coordinate
33  real(kind_real),allocatable :: z(:) ! z-coordinate
34  integer,allocatable :: list(:) ! Stripack list
35  integer,allocatable :: lptr(:) ! Stripack list pointer
36  integer,allocatable :: lend(:) ! Stripack list end
37  integer :: lnew ! Stripack pointer to the first empty location in list
38  integer :: nb ! Number of boundary nodes
39  integer,allocatable :: bnd(:) ! Boundary nodes
40 
41  ! Triangles data
42  integer :: nt ! Number of triangles
43  integer :: na ! Number of arcs
44  integer,allocatable :: ltri(:,:) ! Triangles indices
45  integer,allocatable :: larc(:,:) ! Arcs indices
46  real(kind_real),allocatable :: bdist(:) ! Distance to the closest boundary arc
47 contains
48  procedure :: create => mesh_create
49  procedure :: dealloc => mesh_dealloc
50  procedure :: copy => mesh_copy
51  procedure :: trans => mesh_trans
52  procedure :: trlist => mesh_trlist
53  procedure :: bnodes => mesh_bnodes
54  procedure :: barcs => mesh_barcs
55  procedure :: check => mesh_check
56  procedure :: inside => mesh_inside
57  procedure :: barycentric => mesh_barycentric
58  procedure :: addnode => mesh_addnode
59  procedure :: polygon => mesh_polygon
60 end type mesh_type
61 
62 private
63 public :: mesh_type
64 
65 contains
66 
67 !----------------------------------------------------------------------
68 ! Subroutine: mesh_create
69 ! Purpose: create mesh
70 !----------------------------------------------------------------------
71 subroutine mesh_create(mesh,mpl,rng,n,lon,lat)
72 
73 implicit none
74 
75 ! Passed variables
76 class(mesh_type),intent(inout) :: mesh ! Mesh
77 type(mpl_type),intent(in) :: mpl ! MPI data
78 type(rng_type),intent(inout) :: rng ! Random number generator
79 integer,intent(in) :: n ! Mesh size
80 real(kind_real),intent(in) :: lon(n) ! Longitudes
81 real(kind_real),intent(in) :: lat(n) ! Latitudes
82 
83 ! Local variables
84 integer :: i,k,info
85 integer,allocatable :: jtab(:),near(:),next(:)
86 real(kind_real),allocatable :: dist(:)
87 
88 ! Allocation
89 mesh%n = n
90 
91 ! Allocation
92 allocate(mesh%order(mesh%n))
93 allocate(mesh%order_inv(mesh%n))
94 allocate(mesh%lon(mesh%n))
95 allocate(mesh%lat(mesh%n))
96 allocate(mesh%list(6*(mesh%n-2)))
97 allocate(mesh%lptr(6*(mesh%n-2)))
98 allocate(mesh%lend(mesh%n))
99 allocate(mesh%x(mesh%n))
100 allocate(mesh%y(mesh%n))
101 allocate(mesh%z(mesh%n))
102 allocate(near(mesh%n))
103 allocate(next(mesh%n))
104 allocate(dist(mesh%n))
105 
106 ! Points order
107 do i=1,mesh%n
108  mesh%order(i) = i
109 end do
110 
111 if (shuffle) then
112  ! Shuffle order (more efficient to compute the Delaunay triangulation)
113  allocate(jtab(mesh%n))
114  if (mpl%main) call rng%rand_integer(1,mesh%n,jtab)
115  call mpl%f_comm%broadcast(jtab,mpl%ioproc-1)
116  do i=mesh%n,2,-1
117  k = mesh%order(jtab(i))
118  mesh%order(jtab(i)) = mesh%order(i)
119  mesh%order(i) = k
120  end do
121 end if
122 
123 ! Restrictive inverse order
124 call msi(mesh%order_inv)
125 do i=1,mesh%n
126  mesh%order_inv(mesh%order(i)) = i
127 end do
128 
129 ! Transform to cartesian coordinates
130 call mesh%trans(lon,lat)
131 
132 ! Create mesh
133 mesh%list = 0
134 call trmesh(mpl,mesh%n,mesh%x,mesh%y,mesh%z,mesh%list,mesh%lptr,mesh%lend,mesh%lnew,near,next,dist,info)
135 
136 end subroutine mesh_create
137 
138 !----------------------------------------------------------------------
139 ! Subroutine: mesh_dealloc
140 ! Purpose: deallocate mesh
141 !----------------------------------------------------------------------
142 subroutine mesh_dealloc(mesh)
144 implicit none
145 
146 ! Passed variables
147 class(mesh_type),intent(inout) :: mesh ! Mesh
148 
149 ! Release memory
150 if (allocated(mesh%order)) deallocate(mesh%order)
151 if (allocated(mesh%order_inv)) deallocate(mesh%order_inv)
152 if (allocated(mesh%lon)) deallocate(mesh%lon)
153 if (allocated(mesh%lat)) deallocate(mesh%lat)
154 if (allocated(mesh%x)) deallocate(mesh%x)
155 if (allocated(mesh%y)) deallocate(mesh%y)
156 if (allocated(mesh%z)) deallocate(mesh%z)
157 if (allocated(mesh%list)) deallocate(mesh%list)
158 if (allocated(mesh%lptr)) deallocate(mesh%lptr)
159 if (allocated(mesh%lend)) deallocate(mesh%lend)
160 if (allocated(mesh%bnd)) deallocate(mesh%bnd)
161 if (allocated(mesh%ltri)) deallocate(mesh%ltri)
162 if (allocated(mesh%larc)) deallocate(mesh%larc)
163 if (allocated(mesh%bdist)) deallocate(mesh%bdist)
164 
165 end subroutine mesh_dealloc
166 
167 !----------------------------------------------------------------------
168 ! Function: mesh_copy
169 ! Purpose: copy mesh
170 !----------------------------------------------------------------------
171 type(mesh_type) function mesh_copy(mesh)
173 implicit none
174 
175 ! Passed variables
176 class(mesh_type),intent(in) :: mesh ! Input mesh
177 
178 ! Copy sizes
179 mesh_copy%n = mesh%n
180 if (allocated(mesh%ltri)) then
181  mesh_copy%nt = mesh%nt
182  mesh_copy%na = mesh%na
183 end if
184 
185 ! Release memory
186 call mesh_copy%dealloc
187 
188 ! Allocation
189 allocate(mesh_copy%order(mesh_copy%n))
190 allocate(mesh_copy%order_inv(mesh_copy%n))
191 allocate(mesh_copy%lon(mesh_copy%n))
192 allocate(mesh_copy%lat(mesh_copy%n))
193 allocate(mesh_copy%x(mesh_copy%n))
194 allocate(mesh_copy%y(mesh_copy%n))
195 allocate(mesh_copy%z(mesh_copy%n))
196 allocate(mesh_copy%list(6*(mesh_copy%n-2)))
197 allocate(mesh_copy%lptr(6*(mesh_copy%n-2)))
198 allocate(mesh_copy%lend(mesh_copy%n))
199 if (allocated(mesh%ltri)) then
200  allocate(mesh_copy%ltri(3,mesh_copy%nt))
201  allocate(mesh_copy%larc(2,mesh_copy%na))
202  allocate(mesh_copy%bdist(mesh_copy%n))
203 end if
204 
205 ! Copy data
206 mesh_copy%order = mesh%order
207 mesh_copy%order_inv = mesh%order_inv
208 mesh_copy%lon = mesh%lon
209 mesh_copy%lat = mesh%lat
210 mesh_copy%x = mesh%x
211 mesh_copy%y = mesh%y
212 mesh_copy%z = mesh%z
213 mesh_copy%list = mesh%list
214 mesh_copy%lptr = mesh%lptr
215 mesh_copy%lend = mesh%lend
216 mesh_copy%lnew = mesh%lnew
217 if (allocated(mesh%ltri)) then
218  mesh_copy%nb = mesh%nb
219  mesh_copy%ltri = mesh%ltri
220  mesh_copy%larc = mesh%larc
221  mesh_copy%bdist = mesh%bdist
222 end if
223 
224 end function mesh_copy
225 
226 !----------------------------------------------------------------------
227 ! Subroutine: mesh_trans
228 ! Purpose: transform to cartesian coordinates
229 !----------------------------------------------------------------------
230 subroutine mesh_trans(mesh,lon,lat)
232 implicit none
233 
234 ! Passed variables
235 class(mesh_type),intent(inout) :: mesh ! Mesh
236 real(kind_real),intent(in) :: lon(mesh%n) ! Longitude
237 real(kind_real),intent(in) :: lat(mesh%n) ! Latitude
238 
239 ! Copy lon/lat
240 mesh%lon = lon(mesh%order)
241 mesh%lat = lat(mesh%order)
242 
243 ! Transform to cartesian coordinates
244 call trans(mesh%n,mesh%lat,mesh%lon,mesh%x,mesh%y,mesh%z)
245 
246 end subroutine mesh_trans
247 
248 !----------------------------------------------------------------------
249 ! Subroutine: mesh_trlist
250 ! Purpose: compute triangle list, arc list
251 !----------------------------------------------------------------------
252 subroutine mesh_trlist(mesh)
254 implicit none
255 
256 ! Passed variables
257 class(mesh_type),intent(inout) :: mesh ! Mesh
258 
259 ! Local variables
260 integer :: info
261 integer,allocatable :: ltri(:,:)
262 integer :: ia,it,i,i1,i2
263 
264 ! Allocation
265 allocate(ltri(9,2*(mesh%n-2)))
266 
267 ! Create triangles list
268 call trlist(mesh%n,mesh%list,mesh%lptr,mesh%lend,9,mesh%nt,ltri,info)
269 
270 ! Allocation
271 mesh%na = maxval(ltri(7:9,1:mesh%nt))
272 allocate(mesh%ltri(3,mesh%nt))
273 allocate(mesh%larc(2,mesh%na))
274 
275 ! Copy triangle list
276 mesh%ltri = ltri(1:3,1:mesh%nt)
277 
278 ! Copy arcs list
279 do ia=1,mesh%na
280  it = 1
281  do while (it<=mesh%nt)
282  if (any(ltri(7:9,it)==ia)) exit
283  it = it+1
284  end do
285  i = 1
286  do while (i<=3)
287  if (ltri(6+i,it)==ia) exit
288  i = i+1
289  end do
290  i1 = mod(i+1,3)
291  if (i1==0) i1 = 3
292  i2 = mod(i+2,3)
293  if (i2==0) i2 = 3
294  mesh%larc(1,ia) = ltri(i1,it)
295  mesh%larc(2,ia) = ltri(i2,it)
296 end do
297 
298 end subroutine mesh_trlist
299 
300 !----------------------------------------------------------------------
301 ! Subroutine: mesh_bnodes
302 ! Purpose: find boundary nodes
303 !----------------------------------------------------------------------
304 subroutine mesh_bnodes(mesh)
306 implicit none
307 
308 ! Passed variables
309 class(mesh_type),intent(inout) :: mesh ! Mesh
310 
311 ! Allocation
312 allocate(mesh%bnd(mesh%n))
313 
314 ! Find boundary nodes
315 call msi(mesh%bnd)
316 call bnodes(mesh%n,mesh%list,mesh%lptr,mesh%lend,mesh%bnd,mesh%nb,mesh%na,mesh%nt)
317 
318 end subroutine mesh_bnodes
319 
320 !----------------------------------------------------------------------
321 ! Subroutine: mesh_barcs
322 ! Purpose: find boundary arcs
323 !----------------------------------------------------------------------
324 subroutine mesh_barcs(mesh)
326 implicit none
327 
328 ! Passed variables
329 class(mesh_type),intent(inout) :: mesh ! Mesh
330 
331 ! Local variables
332 integer :: i
333 integer,allocatable :: larcb(:,:)
334 integer :: ia,nab,iab
335 real(kind_real) :: dist_12,v1(3),v2(3),vp(3),v(3),vf(3),vt(3),tlat,tlon,trad,dist_t1,dist_t2
336 
337 ! Allocation
338 allocate(larcb(2,3*(mesh%n-2)))
339 allocate(mesh%bdist(mesh%n))
340 
341 if (mesh%nb>0) then
342  ! Find boundary arcs
343  nab = 0
344  do ia=1,mesh%na
345  if (any(mesh%bnd(1:mesh%nb)==mesh%larc(1,ia)).and.any(mesh%bnd(1:mesh%nb)==mesh%larc(2,ia))) then
346  nab = nab+1
347  larcb(:,nab) = mesh%larc(:,ia)
348  end if
349  end do
350 
351  ! Find minimal distance to a boundary arc
352  mesh%bdist = huge(1.0)
353  do iab=1,nab
354  ! Distance
355  call sphere_dist(mesh%lon(larcb(1,iab)),mesh%lat(larcb(1,iab)), &
356  & mesh%lon(larcb(2,iab)),mesh%lat(larcb(2,iab)),dist_12)
357 
358  ! Vectors
359  v1 = (/mesh%x(larcb(1,iab)),mesh%y(larcb(1,iab)),mesh%z(larcb(1,iab))/)
360  v2 = (/mesh%x(larcb(2,iab)),mesh%y(larcb(2,iab)),mesh%z(larcb(2,iab))/)
361 
362  ! Compute normal vector to the boundary arc plane
363  call vector_product(v1,v2,vp)
364 
365  ! Compute the shortest distance from each point to the boundary arc great-circle
366  do i=1,mesh%n
367  ! Vector
368  v = (/mesh%x(i),mesh%y(i),mesh%z(i)/)
369 
370  ! Vector products
371  call vector_product(v,vp,vf)
372  call vector_product(vp,vf,vt)
373 
374  ! Back to spherical coordinates
375  call scoord(vt(1),vt(2),vt(3),tlat,tlon,trad)
376 
377  ! Check whether T is on the arc
378  call sphere_dist(tlon,tlat,mesh%lon(larcb(1,iab)),mesh%lat(larcb(1,iab)),dist_t1)
379  call sphere_dist(tlon,tlat,mesh%lon(larcb(2,iab)),mesh%lat(larcb(2,iab)),dist_t2)
380  if ((dist_t1<dist_12).and.(dist_t2<dist_12)) then
381  ! T is on the arc
382  call sphere_dist(mesh%lon(i),mesh%lat(i),tlon,tlat,dist_t1)
383  mesh%bdist(i) = min(mesh%bdist(i),dist_t1)
384  else
385  ! T is not on the arc
386  call sphere_dist(mesh%lon(i),mesh%lat(i),mesh%lon(larcb(1,iab)),mesh%lat(larcb(1,iab)),dist_t1)
387  call sphere_dist(mesh%lon(i),mesh%lat(i),mesh%lon(larcb(2,iab)),mesh%lat(larcb(2,iab)),dist_t2)
388  mesh%bdist(i) = min(mesh%bdist(i),min(dist_t1,dist_t2))
389  end if
390  end do
391  end do
392 else
393  mesh%bdist = huge(1.0)
394 end if
395 
396 end subroutine mesh_barcs
397 
398 !----------------------------------------------------------------------
399 ! Subroutine: mesh_check
400 ! Purpose: check whether the mesh is made of counter-clockwise triangles
401 !----------------------------------------------------------------------
402 subroutine mesh_check(mesh,valid)
404 implicit none
405 
406 ! Passed variables
407 class(mesh_type),intent(inout) :: mesh ! Mesh
408 real(kind_real),intent(out) :: valid(mesh%n) ! Validity flag (1.0 if the vertex is valid, else 0.0)
409 
410 ! Local variables
411 integer :: it
412 real(kind_real),allocatable :: a(:),b(:),c(:),cd(:),cp(:)
413 logical :: validt(mesh%nt)
414 
415 !$omp parallel do schedule(static) private(it) firstprivate(a,b,c,cd,cp)
416 do it=1,mesh%nt
417  ! Allocation
418  allocate(a(3))
419  allocate(b(3))
420  allocate(c(3))
421  allocate(cd(3))
422  allocate(cp(3))
423 
424  ! Check vertices status
425  if (isallnotmsr(mesh%x(mesh%ltri(:,it))).and.isallnotmsr(mesh%y(mesh%ltri(:,it))).and.isallnotmsr(mesh%z(mesh%ltri(:,it)))) then
426  ! Vertices
427  a = (/mesh%x(mesh%ltri(1,it)),mesh%y(mesh%ltri(1,it)),mesh%z(mesh%ltri(1,it))/)
428  b = (/mesh%x(mesh%ltri(2,it)),mesh%y(mesh%ltri(2,it)),mesh%z(mesh%ltri(2,it))/)
429  c = (/mesh%x(mesh%ltri(3,it)),mesh%y(mesh%ltri(3,it)),mesh%z(mesh%ltri(3,it))/)
430 
431  ! Cross-product (c-b)x(a-b)
432  call vector_product(c-b,a-b,cp)
433 
434  ! Centroid
435  cd = (a+b+c)/3.0
436 
437  ! Compare the directions
438  validt(it) = sum(cp*cd)>0.0
439  else
440  ! At least one vertex ic1 ms
441  validt(it) = .false.
442  end if
443 
444  ! Release memory
445  deallocate(a)
446  deallocate(b)
447  deallocate(c)
448  deallocate(cd)
449  deallocate(cp)
450 end do
451 !$omp end parallel do
452 
453 ! Check vertices
454 valid = 1.0
455 do it=1,mesh%nt
456  if (.not.validt(it)) valid(mesh%ltri(:,it)) = 0.0
457 end do
458 
459 end subroutine mesh_check
460 
461 !----------------------------------------------------------------------
462 ! Subroutine: mesh_inside
463 ! Purpose: find whether a point is inside the mesh
464 !----------------------------------------------------------------------
465 subroutine mesh_inside(mesh,lon,lat,inside_mesh)
467 implicit none
468 
469 ! Passed variables
470 class(mesh_type),intent(in) :: mesh ! Mesh
471 real(kind_real),intent(in) :: lon(1) ! Longitude
472 real(kind_real),intent(in) :: lat(1) ! Latitude
473 logical,intent(out) :: inside_mesh ! True if the point is inside the mesh
474 
475 ! Local variables
476 integer :: info
477 real(kind_real) :: p(3)
478 
479 if (mesh%nb>0) then
480  ! Transform to cartesian coordinates
481  call trans(1,lat,lon,p(1),p(2),p(3))
482 
483  ! Find answer
484  inside_mesh = inside(p,mesh%n,mesh%x,mesh%y,mesh%z,mesh%nb,mesh%bnd,info)
485 else
486  ! No boundary
487  inside_mesh = .true.
488 end if
489 
490 end subroutine mesh_inside
491 
492 !----------------------------------------------------------------------
493 ! Subroutine: mesh_barycentric
494 ! Purpose: compute barycentric coordinates
495 !----------------------------------------------------------------------
496 subroutine mesh_barycentric(mesh,lon,lat,istart,b,ib)
498 implicit none
499 
500 ! Passed variables
501 class(mesh_type),intent(in) :: mesh ! Mesh
502 real(kind_real),intent(in) :: lon(1) ! Longitude
503 real(kind_real),intent(in) :: lat(1) ! Latitude
504 integer,intent(in) :: istart ! Starting index
505 real(kind_real),intent(out) :: b(3) ! Barycentric weights
506 integer,intent(out) :: ib(3) ! Barycentric indices
507 
508 ! Local variables
509 real(kind_real) :: p(3)
510 
511 ! Transform to cartesian coordinates
512 call trans(1,lat,lon,p(1),p(2),p(3))
513 
514 ! Compute barycentric coordinates
515 b = 0.0
516 ib = 0
517 call trfind(istart,p,mesh%n,mesh%x,mesh%y,mesh%z,mesh%list,mesh%lptr,mesh%lend,b(1),b(2),b(3),ib(1),ib(2),ib(3))
518 
519 end subroutine mesh_barycentric
520 
521 !----------------------------------------------------------------------
522 ! Subroutine: mesh_addnode
523 ! Purpose: add node to a mesh
524 !----------------------------------------------------------------------
525 subroutine mesh_addnode(mesh,mpl,lonnew,latnew)
527 implicit none
528 
529 ! Passed variables
530 class(mesh_type),intent(inout) :: mesh ! Mesh
531 type(mpl_type),intent(in) :: mpl ! MPI data
532 real(kind_real),intent(in) :: lonnew(1) ! Longitude
533 real(kind_real),intent(in) :: latnew(1) ! Latitude
534 
535 ! Local variables
536 integer :: info
537 integer,allocatable :: order(:),order_inv(:),list(:),lptr(:),lend(:)
538 real(kind_real),allocatable :: lon(:),lat(:),x(:),y(:),z(:)
539 
540 ! Allocation
541 allocate(order(mesh%n))
542 allocate(order_inv(mesh%n))
543 allocate(lon(mesh%n))
544 allocate(lat(mesh%n))
545 allocate(x(mesh%n))
546 allocate(y(mesh%n))
547 allocate(z(mesh%n))
548 allocate(list(6*(mesh%n-2)))
549 allocate(lptr(6*(mesh%n-2)))
550 allocate(lend(mesh%n))
551 
552 ! Copy
553 order = mesh%order
554 order_inv = mesh%order_inv
555 lon = mesh%lon
556 lat = mesh%lat
557 x = mesh%x
558 y = mesh%y
559 z = mesh%z
560 list = mesh%list
561 lptr = mesh%lptr
562 lend = mesh%lend
563 
564 ! Release memory
565 call mesh%dealloc
566 
567 ! Reallocate
568 mesh%n = mesh%n+1
569 allocate(mesh%order(mesh%n))
570 allocate(mesh%order_inv(mesh%n))
571 allocate(mesh%lon(mesh%n))
572 allocate(mesh%lat(mesh%n))
573 allocate(mesh%x(mesh%n))
574 allocate(mesh%y(mesh%n))
575 allocate(mesh%z(mesh%n))
576 allocate(mesh%list(6*(mesh%n-2)))
577 allocate(mesh%lptr(6*(mesh%n-2)))
578 allocate(mesh%lend(mesh%n))
579 
580 ! Copy
581 mesh%order(1:mesh%n-1) = order
582 mesh%order_inv(1:mesh%n-1) = order_inv
583 mesh%lon(1:mesh%n-1) = lon
584 mesh%lat(1:mesh%n-1) = lat
585 mesh%x(1:mesh%n-1) = x
586 mesh%y(1:mesh%n-1) = y
587 mesh%z(1:mesh%n-1) = z
588 mesh%list(1:6*(mesh%n-3)) = list
589 mesh%lptr(1:6*(mesh%n-3)) = lptr
590 mesh%lend(1:mesh%n-1) = lend
591 
592 ! Compute new element coordinates
593 call trans(1,latnew,lonnew,mesh%x(mesh%n:mesh%n),mesh%y(mesh%n:mesh%n),mesh%z(mesh%n:mesh%n))
594 
595 ! Update mesh
596 mesh%order(mesh%n) = mesh%n
597 mesh%order_inv(mesh%n) = mesh%n
598 mesh%lon(mesh%n) = lonnew(1)
599 mesh%lat(mesh%n) = latnew(1)
600 call addnod(mpl,1,mesh%n,mesh%x,mesh%y,mesh%z,mesh%list,mesh%lptr,mesh%lend,mesh%lnew,info)
601 
602 end subroutine mesh_addnode
603 
604 !----------------------------------------------------------------------
605 ! Subroutine: mesh_polygon
606 ! Purpose: compute polygon area
607 !----------------------------------------------------------------------
608 subroutine mesh_polygon(mesh,np,plist,area_polygon)
610 implicit none
611 
612 ! Passed variables
613 class(mesh_type),intent(in) :: mesh ! Mesh
614 integer,intent(in) :: np ! Number of points
615 integer,intent(in) :: plist(np) ! List of indices
616 real(kind_real),intent(out) :: area_polygon(np) ! Area
617 
618 ! Local variables
619 integer :: ip,i_src,index_triangle,i_src_last,i_src_new,i_src_stop,vertex_last,vertex_new,nb,info
620 integer :: lnew_tmp,lptr_tmp(6*(mesh%n-2)),lbtri(6,mesh%n),listc(6*(mesh%n-2))
621 real(kind_real) :: area_triangle,v1(3),v2(3),v3(3)
622 real(kind_real) :: xc(6*(mesh%n-2)),yc(6*(mesh%n-2)),zc(6*(mesh%n-2)),rc(6*(mesh%n-2))
623 logical :: loop
624 
625 ! Copy
626 lptr_tmp = mesh%lptr
627 lnew_tmp = mesh%lnew
628 
629 ! Compute Voronoi polygons
630 call crlist(mesh%n,mesh%n,mesh%x,mesh%y,mesh%z,mesh%list,mesh%lend,lptr_tmp,lnew_tmp,lbtri,listc,nb,xc,yc,zc,rc,info)
631 
632 do ip=1,np
633  i_src = plist(ip)
634  area_polygon(ip) = 0.0
635  index_triangle = 0
636  i_src_stop = mesh%lend(i_src)
637  i_src_new = i_src_stop
638  vertex_new = listc(i_src_new)
639  loop = .true.
640  do while (loop)
641  index_triangle = index_triangle+1
642  i_src_last = i_src_new
643  i_src_new = lptr_tmp(i_src_last)
644  vertex_last = vertex_new
645  vertex_new = listc(i_src_new)
646  v1 = (/mesh%x(i_src),mesh%y(i_src),mesh%z(i_src)/)
647  v2 = (/xc(vertex_last),yc(vertex_last),zc(vertex_last)/)
648  v3 = (/xc(vertex_new),yc(vertex_new),zc(vertex_new)/)
649  area_triangle = areas(v1,v2,v3)
650  area_polygon(ip) = area_polygon(ip)+area_triangle
651  loop = (i_src_new/=i_src_stop)
652  end do
653 end do
654 
655 end subroutine mesh_polygon
656 
657 end module type_mesh
type(mesh_type) function mesh_copy(mesh)
Definition: type_mesh.F90:172
subroutine check(action, status)
subroutine mesh_trlist(mesh)
Definition: type_mesh.F90:253
subroutine, public trmesh(mpl, n, x, y, z, list, lptr, lend, lnew, near, next, dist, ier)
subroutine mesh_create(mesh, mpl, rng, n, lon, lat)
Definition: type_mesh.F90:72
subroutine mesh_inside(mesh, lon, lat, inside_mesh)
Definition: type_mesh.F90:466
subroutine mesh_polygon(mesh, np, plist, area_polygon)
Definition: type_mesh.F90:609
subroutine mesh_addnode(mesh, mpl, lonnew, latnew)
Definition: type_mesh.F90:526
subroutine, public copy(self, rhs)
Definition: qg_fields.F90:225
subroutine, public create(self, geom, vars)
Linked list implementation.
Definition: qg_fields.F90:76
subroutine, public trans(n, rlat, rlon, x, y, z)
subroutine, public addnod(mpl, nst, k, x, y, z, list, lptr, lend, lnew, ier)
subroutine mesh_barcs(mesh)
Definition: type_mesh.F90:325
subroutine, public trfind(nst, p, n, x, y, z, list, lptr, lend, b1, b2, b3, i1, i2, i3)
subroutine, public vector_product(v1, v2, vp)
Definition: tools_func.F90:131
subroutine mesh_trans(mesh, lon, lat)
Definition: type_mesh.F90:231
subroutine mesh_check(mesh, valid)
Definition: type_mesh.F90:403
subroutine, public sphere_dist(lon_i, lat_i, lon_f, lat_f, dist)
Definition: tools_func.F90:67
real(kind=kind_real), parameter req
Earth radius at equator (m)
subroutine mesh_barycentric(mesh, lon, lat, istart, b, ib)
Definition: type_mesh.F90:497
real(kind_real) function, public areas(v1, v2, v3)
subroutine mesh_bnodes(mesh)
Definition: type_mesh.F90:305
subroutine, public crlist(n, ncol, x, y, z, list, lend, lptr, lnew, ltri, listc, nb, xc, yc, zc, rc, ier)
subroutine, public scoord(px, py, pz, plat, plon, pnrm)
logical, parameter shuffle
Definition: type_mesh.F90:21
subroutine, public trlist(n, list, lptr, lend, nrow, nt, ltri, ier)
subroutine, public bnodes(n, list, lptr, lend, nodes, nb, na, nt)
integer, parameter, public kind_real
#define min(a, b)
Definition: mosaic_util.h:32
subroutine mesh_dealloc(mesh)
Definition: type_mesh.F90:143
logical function, public inside(p, lv, xv, yv, zv, nv, listv, ier)