53 use mpi_f08,
only : mpi_integer, mpi_max, mpi_sum, mpi_in_place, &
54 mpi_allreduce, mpi_exscan, mpi_request, mpi_status, mpi_wait, &
55 mpi_issend, mpi_irecv, mpi_status_ignore, mpi_integer8, &
60 use,
intrinsic :: iso_fortran_env, only : error_unit
91 logical,
allocatable :: dfrmd_el(:)
99 integer,
allocatable :: facet_neigh(:,:)
108 logical,
allocatable :: neigh(:)
109 integer,
allocatable :: neigh_order(:)
111 integer(2),
allocatable :: facet_type(:,:)
117 logical :: lconn = .false.
118 logical :: ldist = .false.
119 logical :: lnumr = .false.
120 logical :: lgenc = .true.
122 logical :: is_submesh = .false.
126 procedure(
mesh_deform), pass(msh),
pointer :: apply_deform => null()
158 procedure, pass(this) :: check_right_handedness => &
161 generic :: init => init_nelv, init_dist
163 generic :: add_element => add_quad, add_hex
166 generic :: get_local => get_local_point, get_local_edge, get_local_facet
169 generic :: get_global => get_global_edge, get_global_facet
171 generic :: is_shared => is_shared_point, is_shared_edge, is_shared_facet
179 integer,
intent(in) :: lx, ly, lz
180 real(kind=
rp),
intent(inout) :: x(lx, ly, lz, msh%nelv)
181 real(kind=
rp),
intent(inout) :: y(lx, ly, lz, msh%nelv)
182 real(kind=
rp),
intent(inout) :: z(lx, ly, lz, msh%nelv)
193 class(
mesh_t),
intent(inout) :: this
194 integer,
intent(in) :: gdim
195 integer,
intent(in) :: nelv
198 character(len=LOG_SIZE) :: log_buf
211 if (this%nelv < 1)
then
212 write(log_buf,
'(A,I0,A)')
'MPI rank ',
pe_rank,
' has zero elements'
216 call mpi_allreduce(this%nelv, this%glb_nelv, 1, &
220 call mpi_exscan(this%nelv, this%offset_el, 1, &
229 class(
mesh_t),
intent(inout) :: this
230 integer,
intent(in) :: gdim
233 character(len=LOG_SIZE) :: log_buf
241 this%nelv = dist%num_local()
242 if (this%nelv < 1)
then
243 write(log_buf,
'(A,I0,A)')
'MPI rank ',
pe_rank,
' has zero elements'
246 this%glb_nelv = dist%num_global()
247 this%offset_el = dist%start_idx()
255 type(
mesh_t),
intent(inout) :: this
261 allocate(this%elements(this%nelv))
262 allocate(this%dfrmd_el(this%nelv))
263 if (this%gdim .eq. 3)
then
265 allocate(
hex_t::this%elements(i)%e)
271 select type (fmp => this%facet_map)
273 call fmp%init(this%nelv, facet_data)
281 else if (this%gdim .eq. 2)
then
283 allocate(
quad_t::this%elements(i)%e)
288 select type (fmp => this%facet_map)
290 call fmp%init(this%nelv, facet_data)
302 allocate(this%points(this%npts*this%nelv))
308 if (
allocated(this%point_neigh))
then
309 deallocate(this%point_neigh)
311 allocate(this%point_neigh(this%gdim*this%npts*this%nelv))
312 do i = 1, this%gdim*this%npts*this%nelv
313 call this%point_neigh(i)%init(
size = 4)
317 allocate(this%facet_type(2 * this%gdim, this%nelv))
320 call this%htp%init(this%npts*this%nelv, i)
321 call this%htel%init(this%nelv, i)
323 call this%periodic%init(this%nelv)
327 call this%labeled_zones(i)%init(this%nelv)
330 call this%curve%init(this%nelv)
332 call this%ddata%init()
334 allocate(this%neigh(0:
pe_size-1))
345 class(
mesh_t),
intent(inout) :: this
351 call this%htel%free()
352 call this%ddata%free()
353 call this%curve%free()
355 if (
allocated(this%dfrmd_el))
then
356 deallocate(this%dfrmd_el)
359 if (
allocated(this%elements))
then
361 call this%elements(i)%e%free()
362 deallocate(this%elements(i)%e)
364 deallocate(this%elements)
367 if (
allocated(this%facet_map))
then
368 select type (fmp => this%facet_map)
374 deallocate(this%facet_map)
377 if (
allocated(this%facet_neigh))
then
378 deallocate(this%facet_neigh)
381 if (
allocated(this%point_neigh))
then
382 do i = 1, this%gdim * this%npts * this%nelv
383 call this%point_neigh(i)%free()
389 if (
allocated(this%facet_type))
then
390 deallocate(this%facet_type)
392 if (
allocated(this%labeled_zones))
then
394 call this%labeled_zones(i)%free()
396 deallocate(this%labeled_zones)
399 if (
allocated(this%neigh))
then
400 deallocate(this%neigh)
403 if (
allocated(this%neigh_order))
then
404 deallocate(this%neigh_order)
407 if (
allocated(this%points))
then
408 deallocate(this%points)
411 call this%periodic%free()
420 class(
mesh_t),
target,
intent(inout) :: this
426 call this%periodic%finalize()
428 call this%labeled_zones(i)%finalize()
430 call this%curve%finalize()
438 type(
mesh_t),
intent(inout) :: this
439 real(kind=
dp) :: u(3), v(3), w(3), temp
443 if (this%gdim .eq. 2)
then
444 this%dfrmd_el(e) = .false.
445 u = this%elements(e)%e%pts(2)%p%x - this%elements(e)%e%pts(1)%p%x
446 v = this%elements(e)%e%pts(3)%p%x - this%elements(e)%e%pts(1)%p%x
447 temp = u(1)*v(1) + u(2)*v(2)
448 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
450 this%dfrmd_el(e) = .false.
451 u = this%elements(e)%e%pts(2)%p%x - this%elements(e)%e%pts(1)%p%x
452 v = this%elements(e)%e%pts(3)%p%x - this%elements(e)%e%pts(1)%p%x
453 w = this%elements(e)%e%pts(5)%p%x - this%elements(e)%e%pts(1)%p%x
454 temp = u(1)*v(1) + u(2)*v(2) + u(3)*v(3)
455 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
456 temp = u(1)*w(1) + u(2)*w(2) + u(3)*w(3)
457 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
458 u = this%elements(e)%e%pts(7)%p%x - this%elements(e)%e%pts(8)%p%x
459 v = this%elements(e)%e%pts(6)%p%x - this%elements(e)%e%pts(8)%p%x
460 w = this%elements(e)%e%pts(4)%p%x - this%elements(e)%e%pts(8)%p%x
461 temp = u(1)*v(1) + u(2)*v(2) + u(3)*v(3)
462 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
463 temp = u(1)*w(1) + u(2)*w(2) + u(3)*w(3)
464 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
471 class(
mesh_t),
intent(inout) :: this
472 this%dfrmd_el = .true.
477 class(
mesh_t),
target,
intent(inout) :: this
485 integer :: p_local_idx
487 integer :: i, j, k, ierr, el_glb_idx, n_sides, n_nodes, src, dst
489 if (this%lconn)
return
491 if (.not. this%lgenc)
return
495 ep => this%elements(el)%e
500 call this%add_point(ep%pts(i)%p, id)
501 p_local_idx = this%get_local(this%points(id))
504 call this%point_neigh(p_local_idx)%push(id)
507 call ep%facet_id(f, i)
508 call this%add_face(f)
512 call ep%edge_id(e, i)
513 call this%add_edge(e)
518 call this%add_point(ep%pts(i)%p, id)
519 p_local_idx = this%get_local(this%points(id))
522 call this%point_neigh(p_local_idx)%push(id)
526 call ep%facet_id(e, i)
527 call this%add_edge(e)
533 if (this%gdim .eq. 2)
then
542 call mpi_allreduce(this%max_pts_id, this%glb_mpts, 1, &
552 select type (fmp => this%facet_map)
556 el_glb_idx = i + this%offset_el
558 call this%elements(i)%e%facet_id(edge, j)
561 facet_data%x = [0, 0]
564 if (fmp%get(edge, facet_data) .eq. 0)
then
566 if (facet_data%x(1) .eq. el_glb_idx )
then
567 this%facet_neigh(j, i) = facet_data%x(2)
568 else if( facet_data%x(2) .eq. el_glb_idx)
then
569 this%facet_neigh(j, i) = facet_data%x(1)
571 else if(facet_data%x(1) .gt. el_glb_idx)
then
572 facet_data%x(2) = facet_data%x(1)
573 facet_data%x(1) = el_glb_idx
574 this%facet_neigh(j, i) = facet_data%x(2)
575 call fmp%set(edge, facet_data)
576 else if(facet_data%x(1) .lt. el_glb_idx)
then
577 facet_data%x(2) = el_glb_idx
578 this%facet_neigh(j, i) = facet_data%x(1)
579 call fmp%set(edge, facet_data)
582 facet_data%x(1) = el_glb_idx
583 this%facet_neigh(j, i) = facet_data%x(2)
584 call fmp%set(edge, facet_data)
593 el_glb_idx = i + this%offset_el
595 call this%elements(i)%e%facet_id(face, j)
597 facet_data%x = (/ 0, 0/)
600 if (fmp%get(face, facet_data) .eq. 0)
then
602 if (facet_data%x(1) .eq. el_glb_idx )
then
603 this%facet_neigh(j, i) = facet_data%x(2)
604 call this%elements(i)%e%facet_id(face_comp, &
605 j + (2*mod(j, 2) - 1))
606 if (face_comp .eq. face)
then
607 facet_data%x(2) = el_glb_idx
608 this%facet_neigh(j, i) = facet_data%x(1)
609 call fmp%set(face, facet_data)
611 else if( facet_data%x(2) .eq. el_glb_idx)
then
612 this%facet_neigh(j, i) = facet_data%x(1)
614 else if(facet_data%x(1) .gt. el_glb_idx)
then
615 facet_data%x(2) = facet_data%x(1)
616 facet_data%x(1) = el_glb_idx
617 this%facet_neigh(j, i) = facet_data%x(2)
618 call fmp%set(face, facet_data)
619 else if(facet_data%x(1) .lt. el_glb_idx)
then
620 facet_data%x(2) = el_glb_idx
621 this%facet_neigh(j, i) = facet_data%x(1)
622 call fmp%set(face, facet_data)
625 facet_data%x(1) = el_glb_idx
626 this%facet_neigh(j, i) = 0
627 call fmp%set(face, facet_data)
652 if (this%neigh(src) .or. this%neigh(dst))
then
654 call neigh_order%push(j)
658 allocate(this%neigh_order(neigh_order%size()))
659 select type(order => neigh_order%data)
661 do i = 1, neigh_order%size()
662 this%neigh_order(i) = order(i)
665 call neigh_order%free()
669 allocate(this%neigh_order(1))
678 if (this%gdim .eq. 3)
then
691 type(
mesh_t),
intent(inout) :: this
696 type(mpi_status) :: status
697 type(mpi_request) :: send_req, recv_req
698 integer,
allocatable :: recv_buffer(:)
699 integer :: i, j, k, el_glb_idx, n_sides, n_nodes, facet, element, l
700 integer :: max_recv, ierr, src, dst, n_recv, recv_side, neigh_el
703 if (this%gdim .eq. 2)
then
716 el_glb_idx = i + this%offset_el
719 if (this%facet_neigh(j, i) .eq. 0)
then
720 if (n_nodes .eq. 2)
then
721 call this%elements(i)%e%facet_id(edge, j)
722 call buffer%push(el_glb_idx)
725 call buffer%push(edge%x(k))
728 call this%elements(i)%e%facet_id(face, j)
729 call buffer%push(el_glb_idx)
732 call buffer%push(face%x(k))
740 call mpi_allreduce(
buffer%size(), max_recv, 1, &
743 allocate(recv_buffer(max_recv))
745 do i = 1,
size(this%neigh_order)
749 if (this%neigh(src))
then
750 call mpi_irecv(recv_buffer, max_recv, mpi_integer, &
754 if (this%neigh(dst))
then
759 call mpi_issend(
buffer%array(),
buffer%size(), mpi_integer, &
763 if (this%neigh(src))
then
764 call mpi_wait(recv_req, status, ierr)
765 call mpi_get_count(status, mpi_integer, n_recv, ierr)
767 select type (fmp => this%facet_map)
769 do j = 1, n_recv, n_nodes + 2
770 neigh_el = recv_buffer(j)
771 recv_side = recv_buffer(j+1)
773 edge = (/ recv_buffer(j+2), recv_buffer(j+3) /)
775 facet_data = (/ 0, 0 /)
777 if (fmp%get(edge, facet_data) .eq. 0)
then
778 element = facet_data%x(1) - this%offset_el
781 call this%elements(
element)%e%facet_id(edge2, l)
782 if(edge2 .eq. edge)
then
787 this%facet_neigh(facet,
element) = -neigh_el
788 facet_data%x(2) = -neigh_el
791 call fmp%set(edge, facet_data)
793 call this%ddata%set_shared_el_facet(
element, facet)
795 if (this%hte%get(edge, facet) .eq. 0)
then
796 call this%ddata%set_shared_facet(facet)
805 do j = 1, n_recv, n_nodes + 2
806 neigh_el = recv_buffer(j)
807 recv_side = recv_buffer(j+1)
809 face%x = (/ recv_buffer(j+2), recv_buffer(j+3), &
810 recv_buffer(j+4), recv_buffer(j+5) /)
813 facet_data%x = (/ 0, 0 /)
816 if (fmp%get(face, facet_data) .eq. 0)
then
818 element = facet_data%x(1) - this%offset_el
820 call this%elements(
element)%e%facet_id(face2, l)
821 if(face2 .eq. face)
then
826 this%facet_neigh(facet,
element) = -neigh_el
827 facet_data%x(2) = -neigh_el
830 call fmp%set(face, facet_data)
832 call this%ddata%set_shared_el_facet(
element, facet)
834 if (this%htf%get(face, facet) .eq. 0)
then
835 call this%ddata%set_shared_facet(facet)
847 if (this%neigh(dst))
then
848 call mpi_wait(send_req, mpi_status_ignore, ierr)
854 deallocate(recv_buffer)
869 type(
mesh_t),
intent(inout) :: this
871 integer(i8),
allocatable :: buf(:), body(:)
872 integer(i8),
pointer :: cr_data(:)
873 integer,
allocatable :: gkey(:), gperm(:), rpos(:)
874 integer,
contiguous,
pointer :: neighs(:)
875 integer :: i, j, k, n, p, owner, num_neigh, nrec, rlen
876 integer :: pt_glb_idx, pt_loc_idx, src_rank, neigh_el, rk, rp
882 call cr_buf%init(this%mpts * 4)
885 pt_glb_idx = this%points(i)%id()
886 num_neigh = this%point_neigh(i)%size()
887 if (2 + num_neigh .gt.
size(body))
then
889 allocate(body(2 + num_neigh))
891 body(1) = int(pt_glb_idx,
i8)
893 neighs => this%point_neigh(i)%array()
895 body(2 + j) = int(neighs(j),
i8)
897 owner = modulo(pt_glb_idx,
pe_size)
903 allocate(buf(
max(n, 1)))
905 cr_data => cr_buf%array()
906 buf(1:n) = cr_data(1:n)
924 p = p + 2 + int(buf(p + 1))
927 allocate(gkey(
max(nrec, 1)), gperm(
max(nrec, 1)), rpos(
max(nrec, 1)))
933 gkey(nrec) = int(buf(p + 2))
934 p = p + 2 + int(buf(p + 1))
936 if (nrec .gt. 0)
call sort(gkey, gperm, nrec)
938 call cr_buf%init(
max(n, 1))
940 do while (i .le. nrec)
943 do while (j .le. nrec)
944 if (gkey(j) .ne. gkey(i))
exit
950 if (j - i .gt. 1)
then
957 buf(rp + 2 : rp + 1 + int(buf(rp + 1))))
963 deallocate(gkey, gperm, rpos)
966 if (
allocated(buf))
deallocate(buf)
967 allocate(buf(
max(n, 1)))
969 cr_data => cr_buf%array()
970 buf(1:n) = cr_data(1:n)
982 rlen = int(buf(p + 1))
983 pt_glb_idx = int(buf(p + 2))
984 src_rank = int(buf(p + 3))
985 pt_loc_idx = this%have_point_glb_idx(pt_glb_idx)
986 if (pt_loc_idx .gt. 0)
then
987 this%neigh(src_rank) = .true.
988 call this%ddata%set_shared_point(pt_loc_idx)
990 neigh_el = -int(buf(p + 3 + k))
991 call this%point_neigh(pt_loc_idx)%push(neigh_el)
997 if (
allocated(buf))
deallocate(buf)
1005 type(
mesh_t),
target,
intent(inout) :: this
1008 type(
uset_i8_t),
target :: edge_idx, ghost, owner
1011 type(mpi_status) :: status
1012 type(mpi_request) :: send_req, recv_req
1013 integer,
contiguous,
pointer :: p1(:), p2(:), ns_id(:)
1014 integer :: i, j, id, ierr, num_edge_glb, edge_offset, num_edge_loc
1015 integer :: k, l , shared_offset, glb_nshared, n_glb_id
1016 integer(kind=i8) :: C, glb_max, glb_id
1017 integer(kind=i8),
pointer :: glb_ptr
1018 integer(kind=i8),
allocatable :: recv_buff(:)
1019 logical :: shared_edge
1021 integer :: max_recv, src, dst, n_recv
1025 allocate(this%ddata%local_to_global_edge(this%meds))
1027 call edge_idx%init(this%hte%num_entries())
1028 call send_buff%init(this%hte%num_entries())
1029 call owner%init(this%hte%num_entries())
1031 call glb_to_loc%init(32, i)
1039 num_edge_glb = 2* this%meds
1040 call mpi_allreduce(mpi_in_place, num_edge_glb, 1, &
1043 glb_max = int(num_edge_glb,
i8)
1045 call non_shared_edges%init(this%hte%num_entries())
1047 call it%init(this%hte)
1052 k = this%have_point_glb_idx(edge%x(1))
1053 l = this%have_point_glb_idx(edge%x(2))
1054 p1 => this%point_neigh(k)%array()
1055 p2 => this%point_neigh(l)%array()
1057 shared_edge = .false.
1060 do i = 1, this%point_neigh(k)%size()
1061 do j = 1, this%point_neigh(l)%size()
1062 if ((p1(i) .eq. p2(j)) .and. &
1063 (p1(i) .lt. 0) .and. (p2(j) .lt. 0))
then
1064 call this%ddata%set_shared_edge(id)
1065 shared_edge = .true.
1073 if (shared_edge)
then
1074 glb_id = ((int(edge%x(1),
i8)) + int(edge%x(2),
i8)*c) + glb_max
1075 call glb_to_loc%set(glb_id, id)
1076 call edge_idx%add(glb_id)
1077 call owner%add(glb_id)
1078 call send_buff%push(glb_id)
1080 call non_shared_edges%push(id)
1086 num_edge_loc = non_shared_edges%size()
1087 call mpi_exscan(num_edge_loc, edge_offset, 1, &
1089 edge_offset = edge_offset + 1
1092 ns_id => non_shared_edges%array()
1093 do i = 1, non_shared_edges%size()
1094 call this%ddata%set_local_to_global_edge(ns_id(i), edge_offset)
1095 edge_offset = edge_offset + 1
1103 call mpi_allreduce(send_buff%size(), max_recv, 1, &
1106 call ghost%init(send_buff%size())
1108 allocate(recv_buff(max_recv))
1110 do i = 1,
size(this%neigh_order)
1114 if (this%neigh(src))
then
1115 call mpi_irecv(recv_buff, max_recv, mpi_integer8, &
1119 if (this%neigh(dst))
then
1123 select type(sbarray=>send_buff%data)
1124 type is (
integer(i8))
1128 call mpi_issend(sbarray, send_buff%size(), mpi_integer8, &
1133 if (this%neigh(src))
then
1134 call mpi_wait(recv_req, status, ierr)
1135 call mpi_get_count(status, mpi_integer8, n_recv, ierr)
1138 if ((edge_idx%element(recv_buff(j))) .and. (src .lt.
pe_rank))
then
1139 call ghost%add(recv_buff(j))
1140 call owner%remove(recv_buff(j))
1145 if (this%neigh(dst))
then
1146 call mpi_wait(send_req, mpi_status_ignore, ierr)
1152 glb_nshared = num_edge_loc
1153 call mpi_allreduce(mpi_in_place, glb_nshared, 1, &
1157 call mpi_exscan(owner%size(), shared_offset, 1, &
1159 shared_offset = shared_offset + glb_nshared + 1
1162 call send_buff%clear()
1163 call owner%iter_init()
1164 do while (owner%iter_next())
1165 glb_ptr => owner%iter_value()
1166 if (glb_to_loc%get(glb_ptr, id) .eq. 0)
then
1167 call this%ddata%set_local_to_global_edge(id, shared_offset)
1170 call send_buff%push(glb_ptr)
1171 glb_id = int(shared_offset, i8)
1172 call send_buff%push(glb_id)
1174 shared_offset = shared_offset + 1
1183 this%glb_meds = shared_offset -1
1184 call mpi_allreduce(mpi_in_place, this%glb_meds, 1, &
1191 call mpi_allreduce(send_buff%size(), max_recv, 1, &
1194 deallocate(recv_buff)
1195 allocate(recv_buff(max_recv))
1198 do i = 1,
size(this%neigh_order)
1202 if (this%neigh(src))
then
1203 call mpi_irecv(recv_buff, max_recv, mpi_integer8, &
1207 if (this%neigh(dst))
then
1211 select type(sbarray=>send_buff%data)
1212 type is (
integer(i8))
1216 call mpi_issend(sbarray, send_buff%size(), mpi_integer8, &
1221 if (this%neigh(src))
then
1222 call mpi_wait(recv_req, status, ierr)
1223 call mpi_get_count(status, mpi_integer8, n_recv, ierr)
1226 if (ghost%element(recv_buff(j)))
then
1227 if (glb_to_loc%get(recv_buff(j), id) .eq. 0)
then
1228 n_glb_id = int(recv_buff(j + 1 ), 4)
1229 call this%ddata%set_local_to_global_edge(id, n_glb_id)
1237 if (this%neigh(dst))
then
1238 call mpi_wait(send_req, mpi_status_ignore, ierr)
1242 deallocate(recv_buff)
1243 call glb_to_loc%free()
1244 call send_buff%free()
1245 call edge_idx%free()
1246 call non_shared_edges%free()
1254 type(
mesh_t),
target,
intent(inout) :: this
1267 type(mpi_status) :: status
1268 type(mpi_request) :: send_req, recv_req
1269 integer,
allocatable :: recv_buff(:)
1270 integer :: non_shared_facets, shared_facets, facet_offset
1271 integer :: id, glb_nshared, shared_offset, owned_facets
1272 integer :: i, j, ierr, max_recv, src, dst, n_recv
1274 shared_facets = this%ddata%shared_facet%size()
1277 if (this%gdim .eq. 2)
then
1278 allocate(this%ddata%local_to_global_facet(this%meds))
1279 call edge_owner%init(this%meds)
1280 call edge_ghost%init(64, i)
1281 non_shared_facets = this%hte%num_entries() - shared_facets
1283 allocate(this%ddata%local_to_global_facet(this%mfcs))
1284 call face_owner%init(this%mfcs)
1285 call face_ghost%init(64, i)
1286 non_shared_facets = this%htf%num_entries() - shared_facets
1292 call mpi_exscan(non_shared_facets, facet_offset, 1, &
1294 facet_offset = facet_offset + 1
1297 if (this%gdim .eq. 2)
then
1298 call edge_it%init(this%hte)
1299 do while (edge_it%next())
1300 call edge_it%data(id)
1301 edge => edge_it%key()
1302 if (.not. this%ddata%shared_facet%element(id))
then
1303 call this%ddata%set_local_to_global_facet(id, facet_offset)
1304 facet_offset = facet_offset + 1
1306 select type(fmp => this%facet_map)
1308 if (fmp%get(edge, facet_data) .eq. 0)
then
1309 if (facet_data%x(2) .lt. 0)
then
1310 if (abs(facet_data%x(2)) .lt. (this%offset_el + 1))
then
1311 call edge_ghost%set(edge, id)
1313 call edge_owner%push(edge)
1322 owned_facets = edge_owner%size()
1324 call face_it%init(this%htf)
1325 do while (face_it%next())
1326 call face_it%data(id)
1327 face => face_it%key()
1328 if (.not. this%ddata%shared_facet%element(id))
then
1329 call this%ddata%set_local_to_global_facet(id, facet_offset)
1330 facet_offset = facet_offset + 1
1332 select type(fmp => this%facet_map)
1334 if (fmp%get(face, facet_data) .eq. 0)
then
1335 if (facet_data%x(2) .lt. 0)
then
1336 if (abs(facet_data%x(2)) .lt. (this%offset_el + 1))
then
1337 call face_ghost%set(face, id)
1339 call face_owner%push(face)
1348 owned_facets = face_owner%size()
1352 glb_nshared = non_shared_facets
1353 call mpi_allreduce(mpi_in_place, glb_nshared, 1, &
1357 call mpi_exscan(owned_facets, shared_offset, 1, &
1359 shared_offset = shared_offset + glb_nshared + 1
1361 if (this%gdim .eq. 2)
then
1363 if (owned_facets .gt. 32)
then
1364 call send_buff%init(owned_facets)
1366 call send_buff%init()
1369 ed => edge_owner%array()
1370 do i = 1, edge_owner%size()
1371 if (this%hte%get(ed(i), id) .eq. 0)
then
1372 call this%ddata%set_local_to_global_facet(id, shared_offset)
1377 call send_buff%push(ed(i)%x(j))
1379 call send_buff%push(shared_offset)
1381 shared_offset = shared_offset + 1
1387 if (owned_facets .gt. 32)
then
1388 call send_buff%init(owned_facets)
1390 call send_buff%init()
1393 fd => face_owner%array()
1394 do i = 1, face_owner%size()
1395 if (this%htf%get(fd(i), id) .eq. 0)
then
1396 call this%ddata%set_local_to_global_facet(id, shared_offset)
1401 call send_buff%push(fd(i)%x(j))
1403 call send_buff%push(shared_offset)
1405 shared_offset = shared_offset + 1
1414 this%glb_mfcs = shared_offset - 1
1415 call mpi_allreduce(mpi_in_place, this%glb_mfcs, 1, &
1422 call mpi_allreduce(send_buff%size(), max_recv, 1, &
1425 allocate(recv_buff(max_recv))
1428 do i = 1,
size(this%neigh_order)
1432 if (this%neigh(src))
then
1433 call mpi_irecv(recv_buff, max_recv, mpi_integer, &
1437 if (this%neigh(dst))
then
1441 call mpi_issend(send_buff%array(), send_buff%size(), mpi_integer, &
1445 if (this%neigh(src))
then
1446 call mpi_wait(recv_req, status, ierr)
1447 call mpi_get_count(status, mpi_integer, n_recv, ierr)
1449 if (this%gdim .eq. 2)
then
1452 recv_edge = (/recv_buff(j), recv_buff(j+1)/)
1455 if (edge_ghost%get(recv_edge, id) .eq. 0)
then
1456 call this%ddata%set_local_to_global_facet(id, recv_buff(j+2))
1462 recv_face = (/recv_buff(j), recv_buff(j+1), &
1463 recv_buff(j+2), recv_buff(j+3) /)
1466 if (face_ghost%get(recv_face, id) .eq. 0)
then
1467 call this%ddata%set_local_to_global_facet(id, recv_buff(j+4))
1473 if (this%neigh(dst))
then
1474 call mpi_wait(send_req, mpi_status_ignore, ierr)
1479 if (this%gdim .eq. 2)
then
1480 call edge_owner%free()
1481 call edge_ghost%free()
1483 call face_owner%free()
1484 call face_ghost%free()
1487 call send_buff%free()
1488 deallocate(recv_buff)
1495 class(
mesh_t),
target,
intent(inout) :: this
1496 integer,
value :: el, el_glb
1497 type(
point_t),
target,
intent(inout) :: p1, p2, p3, p4
1502 this%lconn = .false.
1505 this%lnumr = .false.
1507 call this%add_point(p1, p(1))
1508 call this%add_point(p2, p(2))
1509 call this%add_point(p3, p(3))
1510 call this%add_point(p4, p(4))
1512 select type (ep => this%elements(el)%e)
1514 call ep%init(el_glb, &
1515 this%points(p(1)), this%points(p(2)), &
1516 this%points(p(3)), this%points(p(4)))
1526 subroutine mesh_add_hex(this, el, el_glb, p1, p2, p3, p4, p5, p6, p7, p8)
1527 class(
mesh_t),
target,
intent(inout) :: this
1528 integer,
value :: el, el_glb
1529 type(
point_t),
target,
intent(inout) :: p1, p2, p3, p4, p5, p6, p7, p8
1535 this%lconn = .false.
1538 this%lnumr = .false.
1540 call this%add_point(p1, p(1))
1541 call this%add_point(p2, p(2))
1542 call this%add_point(p3, p(3))
1543 call this%add_point(p4, p(4))
1544 call this%add_point(p5, p(5))
1545 call this%add_point(p6, p(6))
1546 call this%add_point(p7, p(7))
1547 call this%add_point(p8, p(8))
1550 call this%htel%set(el_glb, el)
1552 select type (ep => this%elements(el)%e)
1554 call ep%init(el_glb, &
1555 this%points(p(1)), this%points(p(2)), &
1556 this%points(p(3)), this%points(p(4)), &
1557 this%points(p(5)), this%points(p(6)), &
1558 this%points(p(7)), this%points(p(8)))
1567 class(
mesh_t),
intent(inout) :: this
1568 type(
point_t),
intent(inout) :: p
1569 integer,
intent(inout) :: idx
1574 this%max_pts_id =
max(this%max_pts_id, tmp)
1576 if (tmp .le. 0)
then
1580 if (this%htp%get(tmp, idx) .gt. 0)
then
1581 this%mpts = this%mpts + 1
1582 call this%htp%set(tmp, this%mpts)
1583 this%points(this%mpts) = p
1591 class(
mesh_t),
intent(inout) :: this
1595 if (this%htf%get(f, idx) .gt. 0)
then
1596 this%mfcs = this%mfcs + 1
1597 call this%htf%set(f, this%mfcs)
1604 class(
mesh_t),
intent(inout) :: this
1608 if (this%hte%get(e, idx) .gt. 0)
then
1609 this%meds = this%meds + 1
1610 call this%hte%set(e, this%meds)
1617 class(
mesh_t),
intent(inout) :: this
1618 integer,
intent(in) :: e
1619 real(kind=
dp),
dimension(5,12),
intent(in) :: curve_data
1620 integer,
dimension(12),
intent(in) :: curve_type
1622 if (e .gt. this%nelv)
then
1625 if ((this%gdim .eq. 2 .and. sum(curve_type(5:8)) .gt. 0) )
then
1628 call this%curve%add_element(e, curve_data, curve_type)
1634 class(
mesh_t),
intent(inout) :: this
1635 integer,
intent(in) :: f
1636 integer,
intent(in) :: e
1637 integer,
intent(in) :: label
1639 if (e .gt. this%nelv)
then
1643 if ((this%gdim .eq. 2 .and. f .gt. 4) .or. &
1644 (this%gdim .eq. 3 .and. f .gt. 6))
then
1647 call this%labeled_zones(label)%add_facet(f, e)
1648 this%facet_type(f,e) = -label
1654 class(
mesh_t),
intent(inout) :: this
1655 integer,
intent(in) :: f
1656 integer,
intent(in) :: e
1657 integer,
intent(in) :: pf
1658 integer,
intent(in) :: pe
1659 integer,
intent(inout) :: pids(4)
1660 integer,
dimension(4) :: org_ids
1662 call this%get_facet_ids(f, e, org_ids)
1663 call this%periodic%add_periodic_facet(f, e, pf, pe, pids, org_ids)
1668 class(
mesh_t),
intent(inout) :: this
1669 integer,
intent(in) :: f
1670 integer,
intent(in) :: e
1671 integer,
intent(inout) :: pids(4)
1676 select type(ele => this%elements(e)%e)
1678 call ele%facet_order(t,f)
1681 call ele%facet_order(t2,f)
1691 class(
mesh_t),
intent(inout) :: this
1697 integer :: org_ids(4), pids(4)
1699 integer,
dimension(4, 6) :: face_nodes = reshape([ &
1707 integer,
dimension(2, 4) :: edge_nodes = reshape([ &
1714 do i = 1, this%periodic%size
1715 e = this%periodic%facet_el(i)%x(2)
1716 f = this%periodic%facet_el(i)%x(1)
1717 pe = this%periodic%p_facet_el(i)%x(2)
1718 pf = this%periodic%p_facet_el(i)%x(1)
1719 pids = this%periodic%p_ids(i)%x
1720 call this%get_facet_ids(f, e, pids)
1721 this%periodic%p_ids(i)%x = pids
1723 do i = 1, this%periodic%size
1724 e = this%periodic%facet_el(i)%x(2)
1725 f = this%periodic%facet_el(i)%x(1)
1726 org_ids = this%periodic%org_ids(i)%x
1727 select type(ele => this%elements(e)%e)
1730 pi => ele%pts(face_nodes(j,f))%p
1731 call pi%set_id(org_ids(j))
1735 pi => ele%pts(edge_nodes(j,f))%p
1736 call pi%set_id(org_ids(j))
1744 class(
mesh_t),
intent(inout) :: this
1745 integer,
intent(in) :: f
1746 integer,
intent(in) :: e
1747 integer,
intent(in) :: pf
1748 integer,
intent(in) :: pe
1749 type(
point_t),
pointer :: pi, pj
1750 real(kind=
dp) :: l(3)
1751 integer :: i, j, id, p_local_idx, match
1754 integer :: envvar_len
1755 character(len=255) :: tol_str
1756 real(kind=
dp) :: tol
1757 integer,
dimension(4, 6) :: face_nodes = reshape([&
1765 integer,
dimension(2, 4) :: edge_nodes = reshape([&
1772 call get_environment_variable(
"NEKO_PERIODIC_TOL", tol_str, envvar_len)
1773 if (envvar_len .gt. 0)
then
1774 read(tol_str(1:envvar_len), *) tol
1779 select type(ele => this%elements(e)%e)
1781 select type(elp => this%elements(pe)%e)
1785 l = l + ele%pts(face_nodes(i,f))%p%x(1:3) - &
1786 elp%pts(face_nodes(i,pf))%p%x(1:3)
1790 pi => ele%pts(face_nodes(i,f))%p
1793 pj => elp%pts(face_nodes(j,pf))%p
1794 if (norm2(pi%x(1:3) - pj%x(1:3) - l) .lt. tol)
then
1795 id = min(pi%id(), pj%id())
1798 p_local_idx = this%get_local(this%points(id))
1802 if ( match .gt. 1)
then
1803 call neko_error(
'Multiple matches when creating periodic ids')
1804 else if (match .eq. 0)
then
1805 call neko_error(
'Cannot find matching periodic point')
1810 select type(elp => this%elements(pe)%e)
1814 l = l + ele%pts(edge_nodes(i,f))%p%x(1:3) - &
1815 elp%pts(edge_nodes(i,pf))%p%x(1:3)
1819 pi => ele%pts(edge_nodes(i,f))%p
1821 pj => elp%pts(edge_nodes(j,pf))%p
1823 if (norm2(pi%x(1:3) - pj%x(1:3) - l) .lt. tol)
then
1824 id = min(pi%id(), pj%id())
1827 p_local_idx = this%get_local(this%points(id))
1838 class(
mesh_t),
intent(inout) :: this
1839 integer,
intent(in) :: f
1840 integer,
intent(in) :: e
1841 integer,
intent(in) :: pf
1842 integer,
intent(in) :: pe
1843 integer,
intent(inout) :: pids(4)
1845 integer :: i, id, p_local_idx
1848 integer,
dimension(4, 6) :: face_nodes = reshape([&
1856 select type(ele => this%elements(e)%e)
1859 pi => ele%pts(face_nodes(i,f))%p
1860 call pi%set_id(pids(i))
1861 call this%add_point(pi, id)
1862 p_local_idx = this%get_local(this%points(id))
1870 class(
mesh_t),
intent(inout) :: this
1871 type(
point_t),
intent(inout) :: p
1878 if (this%htp%get(tmp, local_id) .gt. 0)
then
1879 call neko_error(
'Invalid global id (local point)')
1887 class(
mesh_t),
intent(inout) :: this
1891 if (this%hte%get(e, local_id) .gt. 0)
then
1892 call neko_error(
'Invalid global id (local edge)')
1899 class(
mesh_t),
intent(inout) :: this
1903 if (this%htf%get(f, local_id) .gt. 0)
then
1904 call neko_error(
'Invalid global id (local facet)')
1911 class(
mesh_t),
intent(inout) :: this
1913 integer :: global_id
1915 global_id = this%get_local(e)
1917 if (this%gdim .eq. 2)
then
1919 global_id = this%ddata%local_to_global_facet(global_id)
1923 global_id = this%ddata%local_to_global_edge(global_id)
1931 class(
mesh_t),
intent(inout) :: this
1933 integer :: global_id
1935 global_id = this%get_local_facet(f)
1938 global_id = this%ddata%local_to_global_facet(global_id)
1948 class(
mesh_t),
intent(inout) :: this
1949 integer,
intent(inout) :: index
1952 if (this%htp%get(index, local_id) .eq. 1)
then
1961 class(
mesh_t),
intent(inout) :: this
1962 type(
point_t),
intent(inout) :: p
1963 integer :: local_index
1966 local_index = this%get_local(p)
1967 shared = this%ddata%shared_point%element(local_index)
1975 class(
mesh_t),
intent(inout) :: this
1977 integer :: local_index
1979 local_index = this%get_local(e)
1980 if (this%gdim .eq. 2)
then
1981 shared = this%ddata%shared_facet%element(local_index)
1983 shared = this%ddata%shared_edge%element(local_index)
1989 class(
mesh_t),
intent(inout) :: this
1991 integer :: local_index
1994 local_index = this%get_local(f)
1995 shared = this%ddata%shared_facet%element(local_index)
2002 class(
mesh_t),
intent(inout) :: this
2004 real(kind=
rp) :: v(8)
2010 if (this%gdim .eq. 3)
then
2013 this%elements(i)%e%pts(2)%p%x, &
2014 this%elements(i)%e%pts(3)%p%x, &
2015 this%elements(i)%e%pts(5)%p%x, &
2016 this%elements(i)%e%pts(1)%p%x &
2020 this%elements(i)%e%pts(4)%p%x, &
2021 this%elements(i)%e%pts(1)%p%x, &
2022 this%elements(i)%e%pts(6)%p%x, &
2023 this%elements(i)%e%pts(2)%p%x &
2027 this%elements(i)%e%pts(1)%p%x, &
2028 this%elements(i)%e%pts(4)%p%x, &
2029 this%elements(i)%e%pts(7)%p%x, &
2030 this%elements(i)%e%pts(3)%p%x &
2034 this%elements(i)%e%pts(3)%p%x, &
2035 this%elements(i)%e%pts(2)%p%x, &
2036 this%elements(i)%e%pts(8)%p%x, &
2037 this%elements(i)%e%pts(4)%p%x &
2041 this%elements(i)%e%pts(6)%p%x, &
2042 this%elements(i)%e%pts(7)%p%x, &
2043 this%elements(i)%e%pts(1)%p%x, &
2044 this%elements(i)%e%pts(5)%p%x &
2048 this%elements(i)%e%pts(8)%p%x, &
2049 this%elements(i)%e%pts(5)%p%x, &
2050 this%elements(i)%e%pts(2)%p%x, &
2051 this%elements(i)%e%pts(6)%p%x &
2055 this%elements(i)%e%pts(5)%p%x, &
2056 this%elements(i)%e%pts(8)%p%x, &
2057 this%elements(i)%e%pts(3)%p%x, &
2058 this%elements(i)%e%pts(7)%p%x &
2062 this%elements(i)%e%pts(7)%p%x, &
2063 this%elements(i)%e%pts(6)%p%x, &
2064 this%elements(i)%e%pts(4)%p%x, &
2065 this%elements(i)%e%pts(8)%p%x &
2068 if (v(1) .le. 0.0_rp .or. &
2069 v(2) .le. 0.0_rp .or. &
2070 v(3) .le. 0.0_rp .or. &
2071 v(4) .le. 0.0_rp .or. &
2072 v(5) .le. 0.0_rp .or. &
2073 v(6) .le. 0.0_rp .or. &
2074 v(7) .le. 0.0_rp .or. &
2075 v(8) .le. 0.0_rp )
then
2077 centroid = this%elements(i)%e%centroid()
2079 write(error_unit,
'(A, A, I0, A, 3G12.5)')
"*** ERROR ***: ", &
2080 "Wrong orientation of mesh element ", i, &
2081 " with centroid ", centroid%x
2089 call neko_error(
"Some mesh elements are not right-handed")
2102 real(kind=
dp),
dimension(3),
intent(in) :: p1, p2, p3, origin
2104 real(kind=
dp) :: vp1(3), vp2(3), vp3(3), cross(3)
2110 cross(1) = vp1(2)*vp2(3) - vp2(3)*vp1(2)
2111 cross(2) = vp1(3)*vp2(1) - vp1(1)*vp2(3)
2112 cross(3) = vp1(1)*vp2(2) - vp1(2)*vp2(1)
2114 v = cross(1)*vp3(1) + cross(2)*vp3(2) + cross(3)*vp3(3)
2128 class(
mesh_t),
intent(in) :: this
2129 class(
mesh_t),
intent(inout) :: other
2130 type(
mask_t),
intent(in) :: mask
2131 integer,
intent(in) :: lx, ly, lz
2132 integer :: i, j, k, nelv, lxyz, gdim, e_m, nidx(4), nelv_c, el_c, el, i_m
2140 nelv =
mask%size()/lxyz
2141 call other%init(this%gdim, nelv)
2144 if (other%gdim .eq. 2)
then
2145 call neko_error(
"Subset mesh not implemented for 2d")
2146 else if (other%gdim .eq. 3)
then
2148 i_m = 1 + lxyz * (el - 1)
2159 call p(j)%init(this%elements(e_m)%e%pts(j)%p%x, p_id)
2163 call other%add_element(el, el + other%offset_el, &
2164 p(1), p(2), p(3), p(4), &
2165 p(5), p(6), p(7), p(8))
2174 nelv_c = this%curve%size
2175 if (nelv_c .gt. 0)
then
2179 do while (el .le. nelv .and. el_c .le. nelv_c)
2181 i_m = 1 + lxyz * (el - 1)
2185 if (e_m .lt. this%curve%curve_el(el_c)%el_idx)
then
2188 else if (e_m .gt. this%curve%curve_el(el_c)%el_idx)
then
2192 call other%mark_curve_element(el, &
2193 this%curve%curve_el(el_c)%curve_data, &
2194 this%curve%curve_el(el_c)%curve_type)
2203 call other%finalize()
2205 other%is_submesh = .true.
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
Generic buffer that is extended with buffers of varying rank.
integer, public pe_size
MPI size of communicator.
integer, public pe_rank
MPI rank.
type(mpi_comm), public neko_comm
MPI communicator.
Crystal router: scalable all-to-some personalized exchange.
subroutine, public crystal_router_transfer(buf, n)
Route packed records to their destination ranks.
subroutine, public crystal_router_pack(out, dest, body)
Append one record to a packed crystal-router buffer.
Defines a domain as a subset of facets in a mesh.
Defines practical data distributions.
Defines a zone as a subset of facets in a mesh.
Defines a hexahedron element.
integer, parameter, public neko_hex_npts
Number of points.
integer, parameter, public neko_hex_nfcs
Number of faces.
integer, parameter, public neko_hex_neds
Number of edges.
Implements a hash table ADT.
integer, parameter, public log_size
Object for handling masks in Neko.
subroutine mesh_generate_flags(this)
subroutine mesh_generate_facet_numbering(this)
Generate a unique facet numbering.
subroutine mesh_init_dist(this, gdim, dist)
Initialise a mesh this based on a distribution dist.
logical function mesh_is_shared_point(this, p)
Check if a point is shared.
integer, parameter, public neko_msh_max_zlbls
Max num. zone labels.
subroutine mesh_add_face(this, f)
Add a unique face represented as a 4-tuple to the mesh.
integer function mesh_get_global_edge(this, e)
Return the global id of an edge e.
subroutine mesh_generate_edge_conn(this)
Generate element-element connectivity via edges both between internal and between PEs.
subroutine mesh_add_edge(this, e)
Add a unique edge represented as a 2-tuple to the mesh.
subroutine mesh_add_point(this, p, idx)
Add a unique point to the mesh.
subroutine mesh_free(this)
Deallocate a mesh this.
subroutine mesh_mark_labeled_facet(this, f, e, label)
Mark facet f in element e with label.
subroutine mesh_add_quad(this, el, el_glb, p1, p2, p3, p4)
Add a quadrilateral element to the mesh this.
real(kind=dp) function, public parallelepiped_signed_volume(p1, p2, p3, origin)
Compute a signed volume of a parallelepiped formed by three vectors, in turn defined via three points...
integer, parameter, public neko_msh_max_zlbl_len
Max length of a zone label.
subroutine mesh_mark_periodic_facet(this, f, e, pf, pe, pids)
Mark facet f in element e as periodic with (pf, pe)
integer function mesh_get_local_edge(this, e)
Return the local id of an edge e.
subroutine mesh_all_deformed(this)
Set all elements as if they are deformed.
logical function mesh_is_shared_edge(this, e)
Check if an edge is shared.
subroutine mesh_init_common(this)
subroutine mesh_get_facet_ids(this, f, e, pids)
Get original ids of periodic points.
subroutine mesh_create_periodic_ids(this, f, e, pf, pe)
Creates common ids for matching periodic points.
subroutine mesh_reset_periodic_ids(this)
Reset ids of periodic points to their original ids.
subroutine mesh_init_nelv(this, gdim, nelv)
Initialise a mesh this with nelv elements.
logical function mesh_is_shared_facet(this, f)
Check if a facet is shared.
integer function mesh_get_global_facet(this, f)
Return the local id of a face f.
integer function mesh_have_point_glb_idx(this, index)
Check if the mesh has a point given its global index.
subroutine mesh_generate_external_point_conn(this)
Generate element-element connectivity via points between PEs.
subroutine mesh_apply_periodic_facet(this, f, e, pf, pe, pids)
Replaces the periodic point's id with a common id for matching periodic points.
subroutine mesh_finalize(this)
subroutine mesh_generate_external_facet_conn(this)
Generate element-element connectivity via facets between PEs.
subroutine mesh_mark_curve_element(this, e, curve_data, curve_type)
Mark element e as a curve element.
subroutine mesh_check_right_handedness(this)
Check the correct orientation of the rst coordindates.
subroutine mesh_generate_conn(this)
Generate element-to-element connectivity.
subroutine mesh_add_hex(this, el, el_glb, p1, p2, p3, p4, p5, p6, p7, p8)
Add a hexahedral element to the mesh this.
integer function mesh_get_local_facet(this, f)
Return the local id of a face f.
integer function mesh_get_local_point(this, p)
Return the local id of a point p.
subroutine mesh_subset_by_mask(this, other, mask, lx, ly, lz)
Create a subset of the mesh this in other based on the provided mask.
integer, parameter, public i8
integer, parameter, public dp
integer, parameter, public rp
Global precision used in computations.
Defines a quadrilateral element.
integer, parameter, public neko_quad_neds
Number of edges.
integer, parameter, public neko_quad_npts
Number of points.
Implements a dynamic stack ADT.
Implements an unordered set ADT.
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Load-balanced linear distribution .
Base type for an element.
Integer based hash table.
Integer 2-tuple based hash table.
Integer 4-tuple based hash table.
Integer*8 based hash table.
Iterator for an integer based 2-tuple hash table.
Iterator for an integer based 4-tuple hash table.
Base type for a hash table.
Type for consistently handling masks in Neko. This type encapsulates the mask array and its associate...
A point in with coordinates .
Integer 2-tuple based stack.
Integer 4-tuple based stack.
Integer*8 based unordered set.