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
197 character(len=LOG_SIZE) :: log_buf
204 if (this%nelv < 1)
then
205 write(log_buf,
'(A,I0,A)')
'MPI rank ',
pe_rank,
' has zero elements'
209 call mpi_allreduce(this%nelv, this%glb_nelv, 1, &
213 call mpi_exscan(this%nelv, this%offset_el, 1, &
222 class(
mesh_t),
intent(inout) :: this
223 integer,
intent(in) :: gdim
225 character(len=LOG_SIZE) :: log_buf
229 this%nelv = dist%num_local()
230 if (this%nelv < 1)
then
231 write(log_buf,
'(A,I0,A)')
'MPI rank ',
pe_rank,
' has zero elements'
234 this%glb_nelv = dist%num_global()
235 this%offset_el = dist%start_idx()
243 type(
mesh_t),
intent(inout) :: this
249 allocate(this%elements(this%nelv))
250 allocate(this%dfrmd_el(this%nelv))
251 if (this%gdim .eq. 3)
then
253 allocate(
hex_t::this%elements(i)%e)
259 select type (fmp => this%facet_map)
261 call fmp%init(this%nelv, facet_data)
269 else if (this%gdim .eq. 2)
then
271 allocate(
quad_t::this%elements(i)%e)
276 select type (fmp => this%facet_map)
278 call fmp%init(this%nelv, facet_data)
290 allocate(this%points(this%npts*this%nelv))
296 if (
allocated(this%point_neigh))
then
297 deallocate(this%point_neigh)
299 allocate(this%point_neigh(this%gdim*this%npts*this%nelv))
300 do i = 1, this%gdim*this%npts*this%nelv
301 call this%point_neigh(i)%init(size=4)
305 allocate(this%facet_type(2 * this%gdim, this%nelv))
308 call this%htp%init(this%npts*this%nelv, i)
309 call this%htel%init(this%nelv, i)
311 call this%periodic%init(this%nelv)
315 call this%labeled_zones(i)%init(this%nelv)
318 call this%curve%init(this%nelv)
320 call this%ddata%init()
322 allocate(this%neigh(0:
pe_size-1))
333 class(
mesh_t),
intent(inout) :: this
339 call this%htel%free()
340 call this%ddata%free()
341 call this%curve%free()
343 if (
allocated(this%dfrmd_el))
then
344 deallocate(this%dfrmd_el)
347 if (
allocated(this%elements))
then
349 call this%elements(i)%e%free()
350 deallocate(this%elements(i)%e)
352 deallocate(this%elements)
355 if (
allocated(this%facet_map))
then
356 select type (fmp => this%facet_map)
362 deallocate(this%facet_map)
365 if (
allocated(this%facet_neigh))
then
366 deallocate(this%facet_neigh)
369 if (
allocated(this%point_neigh))
then
370 do i = 1, this%gdim * this%npts * this%nelv
371 call this%point_neigh(i)%free()
377 if (
allocated(this%facet_type))
then
378 deallocate(this%facet_type)
380 if (
allocated(this%labeled_zones))
then
382 call this%labeled_zones(i)%free()
384 deallocate(this%labeled_zones)
387 if (
allocated(this%neigh))
then
388 deallocate(this%neigh)
391 if (
allocated(this%neigh_order))
then
392 deallocate(this%neigh_order)
395 if (
allocated(this%points))
then
396 deallocate(this%points)
399 call this%periodic%free()
408 class(
mesh_t),
target,
intent(inout) :: this
414 call this%periodic%finalize()
416 call this%labeled_zones(i)%finalize()
418 call this%curve%finalize()
426 type(
mesh_t),
intent(inout) :: this
427 real(kind=
dp) :: u(3), v(3), w(3), temp
431 if (this%gdim .eq. 2)
then
432 this%dfrmd_el(e) = .false.
433 u = this%elements(e)%e%pts(2)%p%x - this%elements(e)%e%pts(1)%p%x
434 v = this%elements(e)%e%pts(3)%p%x - this%elements(e)%e%pts(1)%p%x
435 temp = u(1)*v(1) + u(2)*v(2)
436 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
438 this%dfrmd_el(e) = .false.
439 u = this%elements(e)%e%pts(2)%p%x - this%elements(e)%e%pts(1)%p%x
440 v = this%elements(e)%e%pts(3)%p%x - this%elements(e)%e%pts(1)%p%x
441 w = this%elements(e)%e%pts(5)%p%x - this%elements(e)%e%pts(1)%p%x
442 temp = u(1)*v(1) + u(2)*v(2) + u(3)*v(3)
443 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
444 temp = u(1)*w(1) + u(2)*w(2) + u(3)*w(3)
445 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
446 u = this%elements(e)%e%pts(7)%p%x - this%elements(e)%e%pts(8)%p%x
447 v = this%elements(e)%e%pts(6)%p%x - this%elements(e)%e%pts(8)%p%x
448 w = this%elements(e)%e%pts(4)%p%x - this%elements(e)%e%pts(8)%p%x
449 temp = u(1)*v(1) + u(2)*v(2) + u(3)*v(3)
450 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
451 temp = u(1)*w(1) + u(2)*w(2) + u(3)*w(3)
452 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
459 class(
mesh_t),
intent(inout) :: this
460 this%dfrmd_el = .true.
465 class(
mesh_t),
target,
intent(inout) :: this
473 integer :: p_local_idx
475 integer :: i, j, k, ierr, el_glb_idx, n_sides, n_nodes, src, dst
477 if (this%lconn)
return
479 if (.not. this%lgenc)
return
483 ep => this%elements(el)%e
488 call this%add_point(ep%pts(i)%p, id)
489 p_local_idx = this%get_local(this%points(id))
492 call this%point_neigh(p_local_idx)%push(id)
495 call ep%facet_id(f, i)
496 call this%add_face(f)
500 call ep%edge_id(e, i)
501 call this%add_edge(e)
506 call this%add_point(ep%pts(i)%p, id)
507 p_local_idx = this%get_local(this%points(id))
510 call this%point_neigh(p_local_idx)%push(id)
514 call ep%facet_id(e, i)
515 call this%add_edge(e)
521 if (this%gdim .eq. 2)
then
530 call mpi_allreduce(this%max_pts_id, this%glb_mpts, 1, &
540 select type (fmp => this%facet_map)
544 el_glb_idx = i + this%offset_el
546 call this%elements(i)%e%facet_id(edge, j)
549 facet_data%x = [0, 0]
552 if (fmp%get(edge, facet_data) .eq. 0)
then
554 if (facet_data%x(1) .eq. el_glb_idx )
then
555 this%facet_neigh(j, i) = facet_data%x(2)
556 else if( facet_data%x(2) .eq. el_glb_idx)
then
557 this%facet_neigh(j, i) = facet_data%x(1)
559 else if(facet_data%x(1) .gt. el_glb_idx)
then
560 facet_data%x(2) = facet_data%x(1)
561 facet_data%x(1) = el_glb_idx
562 this%facet_neigh(j, i) = facet_data%x(2)
563 call fmp%set(edge, facet_data)
564 else if(facet_data%x(1) .lt. el_glb_idx)
then
565 facet_data%x(2) = el_glb_idx
566 this%facet_neigh(j, i) = facet_data%x(1)
567 call fmp%set(edge, facet_data)
570 facet_data%x(1) = el_glb_idx
571 this%facet_neigh(j, i) = facet_data%x(2)
572 call fmp%set(edge, facet_data)
581 el_glb_idx = i + this%offset_el
583 call this%elements(i)%e%facet_id(face, j)
585 facet_data%x = (/ 0, 0/)
588 if (fmp%get(face, facet_data) .eq. 0)
then
590 if (facet_data%x(1) .eq. el_glb_idx )
then
591 this%facet_neigh(j, i) = facet_data%x(2)
592 call this%elements(i)%e%facet_id(face_comp, &
593 j + (2*mod(j, 2) - 1))
594 if (face_comp .eq. face)
then
595 facet_data%x(2) = el_glb_idx
596 this%facet_neigh(j, i) = facet_data%x(1)
597 call fmp%set(face, facet_data)
599 else if( facet_data%x(2) .eq. el_glb_idx)
then
600 this%facet_neigh(j, i) = facet_data%x(1)
602 else if(facet_data%x(1) .gt. el_glb_idx)
then
603 facet_data%x(2) = facet_data%x(1)
604 facet_data%x(1) = el_glb_idx
605 this%facet_neigh(j, i) = facet_data%x(2)
606 call fmp%set(face, facet_data)
607 else if(facet_data%x(1) .lt. el_glb_idx)
then
608 facet_data%x(2) = el_glb_idx
609 this%facet_neigh(j, i) = facet_data%x(1)
610 call fmp%set(face, facet_data)
613 facet_data%x(1) = el_glb_idx
614 this%facet_neigh(j, i) = 0
615 call fmp%set(face, facet_data)
640 if (this%neigh(src) .or. this%neigh(dst))
then
642 call neigh_order%push(j)
646 allocate(this%neigh_order(neigh_order%size()))
647 select type(order => neigh_order%data)
649 do i = 1, neigh_order%size()
650 this%neigh_order(i) = order(i)
653 call neigh_order%free()
657 allocate(this%neigh_order(1))
666 if (this%gdim .eq. 3)
then
679 type(
mesh_t),
intent(inout) :: this
684 type(mpi_status) :: status
685 type(mpi_request) :: send_req, recv_req
686 integer,
allocatable :: recv_buffer(:)
687 integer :: i, j, k, el_glb_idx, n_sides, n_nodes, facet, element, l
688 integer :: max_recv, ierr, src, dst, n_recv, recv_side, neigh_el
691 if (this%gdim .eq. 2)
then
704 el_glb_idx = i + this%offset_el
707 if (this%facet_neigh(j, i) .eq. 0)
then
708 if (n_nodes .eq. 2)
then
709 call this%elements(i)%e%facet_id(edge, j)
710 call buffer%push(el_glb_idx)
713 call buffer%push(edge%x(k))
716 call this%elements(i)%e%facet_id(face, j)
717 call buffer%push(el_glb_idx)
720 call buffer%push(face%x(k))
728 call mpi_allreduce(
buffer%size(), max_recv, 1, &
731 allocate(recv_buffer(max_recv))
733 do i = 1,
size(this%neigh_order)
737 if (this%neigh(src))
then
738 call mpi_irecv(recv_buffer, max_recv, mpi_integer, &
742 if (this%neigh(dst))
then
747 call mpi_issend(
buffer%array(),
buffer%size(), mpi_integer, &
751 if (this%neigh(src))
then
752 call mpi_wait(recv_req, status, ierr)
753 call mpi_get_count(status, mpi_integer, n_recv, ierr)
755 select type (fmp => this%facet_map)
757 do j = 1, n_recv, n_nodes + 2
758 neigh_el = recv_buffer(j)
759 recv_side = recv_buffer(j+1)
761 edge = (/ recv_buffer(j+2), recv_buffer(j+3) /)
763 facet_data = (/ 0, 0 /)
765 if (fmp%get(edge, facet_data) .eq. 0)
then
766 element = facet_data%x(1) - this%offset_el
769 call this%elements(
element)%e%facet_id(edge2, l)
770 if(edge2 .eq. edge)
then
775 this%facet_neigh(facet,
element) = -neigh_el
776 facet_data%x(2) = -neigh_el
779 call fmp%set(edge, facet_data)
781 call this%ddata%set_shared_el_facet(
element, facet)
783 if (this%hte%get(edge, facet) .eq. 0)
then
784 call this%ddata%set_shared_facet(facet)
793 do j = 1, n_recv, n_nodes + 2
794 neigh_el = recv_buffer(j)
795 recv_side = recv_buffer(j+1)
797 face%x = (/ recv_buffer(j+2), recv_buffer(j+3), &
798 recv_buffer(j+4), recv_buffer(j+5) /)
801 facet_data%x = (/ 0, 0 /)
804 if (fmp%get(face, facet_data) .eq. 0)
then
806 element = facet_data%x(1) - this%offset_el
808 call this%elements(
element)%e%facet_id(face2, l)
809 if(face2 .eq. face)
then
814 this%facet_neigh(facet,
element) = -neigh_el
815 facet_data%x(2) = -neigh_el
818 call fmp%set(face, facet_data)
820 call this%ddata%set_shared_el_facet(
element, facet)
822 if (this%htf%get(face, facet) .eq. 0)
then
823 call this%ddata%set_shared_facet(facet)
835 if (this%neigh(dst))
then
836 call mpi_wait(send_req, mpi_status_ignore, ierr)
842 deallocate(recv_buffer)
857 type(
mesh_t),
intent(inout) :: this
859 integer(i8),
allocatable :: buf(:), body(:)
860 integer(i8),
pointer :: cr_data(:)
861 integer,
allocatable :: gkey(:), gperm(:), rpos(:)
862 integer,
contiguous,
pointer :: neighs(:)
863 integer :: i, j, k, n, p, owner, num_neigh, nrec, rlen
864 integer :: pt_glb_idx, pt_loc_idx, src_rank, neigh_el, rk, rp
870 call cr_buf%init(this%mpts * 4)
873 pt_glb_idx = this%points(i)%id()
874 num_neigh = this%point_neigh(i)%size()
875 if (2 + num_neigh .gt.
size(body))
then
877 allocate(body(2 + num_neigh))
879 body(1) = int(pt_glb_idx,
i8)
881 neighs => this%point_neigh(i)%array()
883 body(2 + j) = int(neighs(j),
i8)
885 owner = modulo(pt_glb_idx,
pe_size)
891 allocate(buf(
max(n, 1)))
893 cr_data => cr_buf%array()
894 buf(1:n) = cr_data(1:n)
912 p = p + 2 + int(buf(p + 1))
915 allocate(gkey(
max(nrec, 1)), gperm(
max(nrec, 1)), rpos(
max(nrec, 1)))
921 gkey(nrec) = int(buf(p + 2))
922 p = p + 2 + int(buf(p + 1))
924 if (nrec .gt. 0)
call sort(gkey, gperm, nrec)
926 call cr_buf%init(
max(n, 1))
928 do while (i .le. nrec)
931 do while (j .le. nrec)
932 if (gkey(j) .ne. gkey(i))
exit
938 if (j - i .gt. 1)
then
945 buf(rp + 2 : rp + 1 + int(buf(rp + 1))))
951 deallocate(gkey, gperm, rpos)
954 if (
allocated(buf))
deallocate(buf)
955 allocate(buf(
max(n, 1)))
957 cr_data => cr_buf%array()
958 buf(1:n) = cr_data(1:n)
970 rlen = int(buf(p + 1))
971 pt_glb_idx = int(buf(p + 2))
972 src_rank = int(buf(p + 3))
973 pt_loc_idx = this%have_point_glb_idx(pt_glb_idx)
974 if (pt_loc_idx .gt. 0)
then
975 this%neigh(src_rank) = .true.
976 call this%ddata%set_shared_point(pt_loc_idx)
978 neigh_el = -int(buf(p + 3 + k))
979 call this%point_neigh(pt_loc_idx)%push(neigh_el)
985 if (
allocated(buf))
deallocate(buf)
993 type(
mesh_t),
target,
intent(inout) :: this
996 type(
uset_i8_t),
target :: edge_idx, ghost, owner
999 type(mpi_status) :: status
1000 type(mpi_request) :: send_req, recv_req
1001 integer,
contiguous,
pointer :: p1(:), p2(:), ns_id(:)
1002 integer :: i, j, id, ierr, num_edge_glb, edge_offset, num_edge_loc
1003 integer :: k, l , shared_offset, glb_nshared, n_glb_id
1004 integer(kind=i8) :: C, glb_max, glb_id
1005 integer(kind=i8),
pointer :: glb_ptr
1006 integer(kind=i8),
allocatable :: recv_buff(:)
1007 logical :: shared_edge
1009 integer :: max_recv, src, dst, n_recv
1013 allocate(this%ddata%local_to_global_edge(this%meds))
1015 call edge_idx%init(this%hte%num_entries())
1016 call send_buff%init(this%hte%num_entries())
1017 call owner%init(this%hte%num_entries())
1019 call glb_to_loc%init(32, i)
1027 num_edge_glb = 2* this%meds
1028 call mpi_allreduce(mpi_in_place, num_edge_glb, 1, &
1031 glb_max = int(num_edge_glb,
i8)
1033 call non_shared_edges%init(this%hte%num_entries())
1035 call it%init(this%hte)
1040 k = this%have_point_glb_idx(edge%x(1))
1041 l = this%have_point_glb_idx(edge%x(2))
1042 p1 => this%point_neigh(k)%array()
1043 p2 => this%point_neigh(l)%array()
1045 shared_edge = .false.
1048 do i = 1, this%point_neigh(k)%size()
1049 do j = 1, this%point_neigh(l)%size()
1050 if ((p1(i) .eq. p2(j)) .and. &
1051 (p1(i) .lt. 0) .and. (p2(j) .lt. 0))
then
1052 call this%ddata%set_shared_edge(id)
1053 shared_edge = .true.
1061 if (shared_edge)
then
1062 glb_id = ((int(edge%x(1),
i8)) + int(edge%x(2),
i8)*c) + glb_max
1063 call glb_to_loc%set(glb_id, id)
1064 call edge_idx%add(glb_id)
1065 call owner%add(glb_id)
1066 call send_buff%push(glb_id)
1068 call non_shared_edges%push(id)
1074 num_edge_loc = non_shared_edges%size()
1075 call mpi_exscan(num_edge_loc, edge_offset, 1, &
1077 edge_offset = edge_offset + 1
1080 ns_id => non_shared_edges%array()
1081 do i = 1, non_shared_edges%size()
1082 call this%ddata%set_local_to_global_edge(ns_id(i), edge_offset)
1083 edge_offset = edge_offset + 1
1091 call mpi_allreduce(send_buff%size(), max_recv, 1, &
1094 call ghost%init(send_buff%size())
1096 allocate(recv_buff(max_recv))
1098 do i = 1,
size(this%neigh_order)
1102 if (this%neigh(src))
then
1103 call mpi_irecv(recv_buff, max_recv, mpi_integer8, &
1107 if (this%neigh(dst))
then
1111 select type(sbarray=>send_buff%data)
1112 type is (
integer(i8))
1116 call mpi_issend(sbarray, send_buff%size(), mpi_integer8, &
1121 if (this%neigh(src))
then
1122 call mpi_wait(recv_req, status, ierr)
1123 call mpi_get_count(status, mpi_integer8, n_recv, ierr)
1126 if ((edge_idx%element(recv_buff(j))) .and. (src .lt.
pe_rank))
then
1127 call ghost%add(recv_buff(j))
1128 call owner%remove(recv_buff(j))
1133 if (this%neigh(dst))
then
1134 call mpi_wait(send_req, mpi_status_ignore, ierr)
1140 glb_nshared = num_edge_loc
1141 call mpi_allreduce(mpi_in_place, glb_nshared, 1, &
1145 call mpi_exscan(owner%size(), shared_offset, 1, &
1147 shared_offset = shared_offset + glb_nshared + 1
1150 call send_buff%clear()
1151 call owner%iter_init()
1152 do while (owner%iter_next())
1153 glb_ptr => owner%iter_value()
1154 if (glb_to_loc%get(glb_ptr, id) .eq. 0)
then
1155 call this%ddata%set_local_to_global_edge(id, shared_offset)
1158 call send_buff%push(glb_ptr)
1159 glb_id = int(shared_offset, i8)
1160 call send_buff%push(glb_id)
1162 shared_offset = shared_offset + 1
1171 this%glb_meds = shared_offset -1
1172 call mpi_allreduce(mpi_in_place, this%glb_meds, 1, &
1179 call mpi_allreduce(send_buff%size(), max_recv, 1, &
1182 deallocate(recv_buff)
1183 allocate(recv_buff(max_recv))
1186 do i = 1,
size(this%neigh_order)
1190 if (this%neigh(src))
then
1191 call mpi_irecv(recv_buff, max_recv, mpi_integer8, &
1195 if (this%neigh(dst))
then
1199 select type(sbarray=>send_buff%data)
1200 type is (
integer(i8))
1204 call mpi_issend(sbarray, send_buff%size(), mpi_integer8, &
1209 if (this%neigh(src))
then
1210 call mpi_wait(recv_req, status, ierr)
1211 call mpi_get_count(status, mpi_integer8, n_recv, ierr)
1214 if (ghost%element(recv_buff(j)))
then
1215 if (glb_to_loc%get(recv_buff(j), id) .eq. 0)
then
1216 n_glb_id = int(recv_buff(j + 1 ), 4)
1217 call this%ddata%set_local_to_global_edge(id, n_glb_id)
1225 if (this%neigh(dst))
then
1226 call mpi_wait(send_req, mpi_status_ignore, ierr)
1230 deallocate(recv_buff)
1231 call glb_to_loc%free()
1232 call send_buff%free()
1233 call edge_idx%free()
1234 call non_shared_edges%free()
1242 type(
mesh_t),
target,
intent(inout) :: this
1255 type(mpi_status) :: status
1256 type(mpi_request) :: send_req, recv_req
1257 integer,
allocatable :: recv_buff(:)
1258 integer :: non_shared_facets, shared_facets, facet_offset
1259 integer :: id, glb_nshared, shared_offset, owned_facets
1260 integer :: i, j, ierr, max_recv, src, dst, n_recv
1262 shared_facets = this%ddata%shared_facet%size()
1265 if (this%gdim .eq. 2)
then
1266 allocate(this%ddata%local_to_global_facet(this%meds))
1267 call edge_owner%init(this%meds)
1268 call edge_ghost%init(64, i)
1269 non_shared_facets = this%hte%num_entries() - shared_facets
1271 allocate(this%ddata%local_to_global_facet(this%mfcs))
1272 call face_owner%init(this%mfcs)
1273 call face_ghost%init(64, i)
1274 non_shared_facets = this%htf%num_entries() - shared_facets
1280 call mpi_exscan(non_shared_facets, facet_offset, 1, &
1282 facet_offset = facet_offset + 1
1285 if (this%gdim .eq. 2)
then
1286 call edge_it%init(this%hte)
1287 do while (edge_it%next())
1288 call edge_it%data(id)
1289 edge => edge_it%key()
1290 if (.not. this%ddata%shared_facet%element(id))
then
1291 call this%ddata%set_local_to_global_facet(id, facet_offset)
1292 facet_offset = facet_offset + 1
1294 select type(fmp => this%facet_map)
1296 if (fmp%get(edge, facet_data) .eq. 0)
then
1297 if (facet_data%x(2) .lt. 0)
then
1298 if (abs(facet_data%x(2)) .lt. (this%offset_el + 1))
then
1299 call edge_ghost%set(edge, id)
1301 call edge_owner%push(edge)
1310 owned_facets = edge_owner%size()
1312 call face_it%init(this%htf)
1313 do while (face_it%next())
1314 call face_it%data(id)
1315 face => face_it%key()
1316 if (.not. this%ddata%shared_facet%element(id))
then
1317 call this%ddata%set_local_to_global_facet(id, facet_offset)
1318 facet_offset = facet_offset + 1
1320 select type(fmp => this%facet_map)
1322 if (fmp%get(face, facet_data) .eq. 0)
then
1323 if (facet_data%x(2) .lt. 0)
then
1324 if (abs(facet_data%x(2)) .lt. (this%offset_el + 1))
then
1325 call face_ghost%set(face, id)
1327 call face_owner%push(face)
1336 owned_facets = face_owner%size()
1340 glb_nshared = non_shared_facets
1341 call mpi_allreduce(mpi_in_place, glb_nshared, 1, &
1345 call mpi_exscan(owned_facets, shared_offset, 1, &
1347 shared_offset = shared_offset + glb_nshared + 1
1349 if (this%gdim .eq. 2)
then
1351 if (owned_facets .gt. 32)
then
1352 call send_buff%init(owned_facets)
1354 call send_buff%init()
1357 ed => edge_owner%array()
1358 do i = 1, edge_owner%size()
1359 if (this%hte%get(ed(i), id) .eq. 0)
then
1360 call this%ddata%set_local_to_global_facet(id, shared_offset)
1365 call send_buff%push(ed(i)%x(j))
1367 call send_buff%push(shared_offset)
1369 shared_offset = shared_offset + 1
1375 if (owned_facets .gt. 32)
then
1376 call send_buff%init(owned_facets)
1378 call send_buff%init()
1381 fd => face_owner%array()
1382 do i = 1, face_owner%size()
1383 if (this%htf%get(fd(i), id) .eq. 0)
then
1384 call this%ddata%set_local_to_global_facet(id, shared_offset)
1389 call send_buff%push(fd(i)%x(j))
1391 call send_buff%push(shared_offset)
1393 shared_offset = shared_offset + 1
1402 this%glb_mfcs = shared_offset - 1
1403 call mpi_allreduce(mpi_in_place, this%glb_mfcs, 1, &
1410 call mpi_allreduce(send_buff%size(), max_recv, 1, &
1413 allocate(recv_buff(max_recv))
1416 do i = 1,
size(this%neigh_order)
1420 if (this%neigh(src))
then
1421 call mpi_irecv(recv_buff, max_recv, mpi_integer, &
1425 if (this%neigh(dst))
then
1429 call mpi_issend(send_buff%array(), send_buff%size(), mpi_integer, &
1433 if (this%neigh(src))
then
1434 call mpi_wait(recv_req, status, ierr)
1435 call mpi_get_count(status, mpi_integer, n_recv, ierr)
1437 if (this%gdim .eq. 2)
then
1440 recv_edge = (/recv_buff(j), recv_buff(j+1)/)
1443 if (edge_ghost%get(recv_edge, id) .eq. 0)
then
1444 call this%ddata%set_local_to_global_facet(id, recv_buff(j+2))
1450 recv_face = (/recv_buff(j), recv_buff(j+1), &
1451 recv_buff(j+2), recv_buff(j+3) /)
1454 if (face_ghost%get(recv_face, id) .eq. 0)
then
1455 call this%ddata%set_local_to_global_facet(id, recv_buff(j+4))
1461 if (this%neigh(dst))
then
1462 call mpi_wait(send_req, mpi_status_ignore, ierr)
1467 if (this%gdim .eq. 2)
then
1468 call edge_owner%free()
1469 call edge_ghost%free()
1471 call face_owner%free()
1472 call face_ghost%free()
1475 call send_buff%free()
1476 deallocate(recv_buff)
1483 class(
mesh_t),
target,
intent(inout) :: this
1484 integer,
value :: el, el_glb
1485 type(
point_t),
target,
intent(inout) :: p1, p2, p3, p4
1490 this%lconn = .false.
1493 this%lnumr = .false.
1495 call this%add_point(p1, p(1))
1496 call this%add_point(p2, p(2))
1497 call this%add_point(p3, p(3))
1498 call this%add_point(p4, p(4))
1500 select type (ep => this%elements(el)%e)
1502 call ep%init(el_glb, &
1503 this%points(p(1)), this%points(p(2)), &
1504 this%points(p(3)), this%points(p(4)))
1514 subroutine mesh_add_hex(this, el, el_glb, p1, p2, p3, p4, p5, p6, p7, p8)
1515 class(
mesh_t),
target,
intent(inout) :: this
1516 integer,
value :: el, el_glb
1517 type(
point_t),
target,
intent(inout) :: p1, p2, p3, p4, p5, p6, p7, p8
1523 this%lconn = .false.
1526 this%lnumr = .false.
1528 call this%add_point(p1, p(1))
1529 call this%add_point(p2, p(2))
1530 call this%add_point(p3, p(3))
1531 call this%add_point(p4, p(4))
1532 call this%add_point(p5, p(5))
1533 call this%add_point(p6, p(6))
1534 call this%add_point(p7, p(7))
1535 call this%add_point(p8, p(8))
1538 call this%htel%set(el_glb, el)
1540 select type (ep => this%elements(el)%e)
1542 call ep%init(el_glb, &
1543 this%points(p(1)), this%points(p(2)), &
1544 this%points(p(3)), this%points(p(4)), &
1545 this%points(p(5)), this%points(p(6)), &
1546 this%points(p(7)), this%points(p(8)))
1555 class(
mesh_t),
intent(inout) :: this
1556 type(
point_t),
intent(inout) :: p
1557 integer,
intent(inout) :: idx
1562 this%max_pts_id =
max(this%max_pts_id, tmp)
1564 if (tmp .le. 0)
then
1568 if (this%htp%get(tmp, idx) .gt. 0)
then
1569 this%mpts = this%mpts + 1
1570 call this%htp%set(tmp, this%mpts)
1571 this%points(this%mpts) = p
1579 class(
mesh_t),
intent(inout) :: this
1583 if (this%htf%get(f, idx) .gt. 0)
then
1584 this%mfcs = this%mfcs + 1
1585 call this%htf%set(f, this%mfcs)
1592 class(
mesh_t),
intent(inout) :: this
1596 if (this%hte%get(e, idx) .gt. 0)
then
1597 this%meds = this%meds + 1
1598 call this%hte%set(e, this%meds)
1605 class(
mesh_t),
intent(inout) :: this
1606 integer,
intent(in) :: e
1607 real(kind=
dp),
dimension(5,12),
intent(in) :: curve_data
1608 integer,
dimension(12),
intent(in) :: curve_type
1610 if (e .gt. this%nelv)
then
1613 if ((this%gdim .eq. 2 .and. sum(curve_type(5:8)) .gt. 0) )
then
1616 call this%curve%add_element(e, curve_data, curve_type)
1622 class(
mesh_t),
intent(inout) :: this
1623 integer,
intent(in) :: f
1624 integer,
intent(in) :: e
1625 integer,
intent(in) :: label
1627 if (e .gt. this%nelv)
then
1631 if ((this%gdim .eq. 2 .and. f .gt. 4) .or. &
1632 (this%gdim .eq. 3 .and. f .gt. 6))
then
1635 call this%labeled_zones(label)%add_facet(f, e)
1636 this%facet_type(f,e) = -label
1642 class(
mesh_t),
intent(inout) :: this
1643 integer,
intent(in) :: f
1644 integer,
intent(in) :: e
1645 integer,
intent(in) :: pf
1646 integer,
intent(in) :: pe
1647 integer,
intent(inout) :: pids(4)
1648 integer,
dimension(4) :: org_ids
1650 call this%get_facet_ids(f, e, org_ids)
1651 call this%periodic%add_periodic_facet(f, e, pf, pe, pids, org_ids)
1656 class(
mesh_t),
intent(inout) :: this
1657 integer,
intent(in) :: f
1658 integer,
intent(in) :: e
1659 integer,
intent(inout) :: pids(4)
1664 select type(ele => this%elements(e)%e)
1666 call ele%facet_order(t,f)
1669 call ele%facet_order(t2,f)
1679 class(
mesh_t),
intent(inout) :: this
1685 integer :: org_ids(4), pids(4)
1687 integer,
dimension(4, 6) :: face_nodes = reshape([ &
1695 integer,
dimension(2, 4) :: edge_nodes = reshape([ &
1702 do i = 1, this%periodic%size
1703 e = this%periodic%facet_el(i)%x(2)
1704 f = this%periodic%facet_el(i)%x(1)
1705 pe = this%periodic%p_facet_el(i)%x(2)
1706 pf = this%periodic%p_facet_el(i)%x(1)
1707 pids = this%periodic%p_ids(i)%x
1708 call this%get_facet_ids(f, e, pids)
1709 this%periodic%p_ids(i)%x = pids
1711 do i = 1, this%periodic%size
1712 e = this%periodic%facet_el(i)%x(2)
1713 f = this%periodic%facet_el(i)%x(1)
1714 org_ids = this%periodic%org_ids(i)%x
1715 select type(ele => this%elements(e)%e)
1718 pi => ele%pts(face_nodes(j,f))%p
1719 call pi%set_id(org_ids(j))
1723 pi => ele%pts(edge_nodes(j,f))%p
1724 call pi%set_id(org_ids(j))
1732 class(
mesh_t),
intent(inout) :: this
1733 integer,
intent(in) :: f
1734 integer,
intent(in) :: e
1735 integer,
intent(in) :: pf
1736 integer,
intent(in) :: pe
1737 type(
point_t),
pointer :: pi, pj
1738 real(kind=
dp) :: l(3)
1739 integer :: i, j, id, p_local_idx, match
1742 integer :: envvar_len
1743 character(len=255) :: tol_str
1744 real(kind=
dp) :: tol
1745 integer,
dimension(4, 6) :: face_nodes = reshape([&
1753 integer,
dimension(2, 4) :: edge_nodes = reshape([&
1760 call get_environment_variable(
"NEKO_PERIODIC_TOL", tol_str, envvar_len)
1761 if (envvar_len .gt. 0)
then
1762 read(tol_str(1:envvar_len), *) tol
1767 select type(ele => this%elements(e)%e)
1769 select type(elp => this%elements(pe)%e)
1773 l = l + ele%pts(face_nodes(i,f))%p%x(1:3) - &
1774 elp%pts(face_nodes(i,pf))%p%x(1:3)
1778 pi => ele%pts(face_nodes(i,f))%p
1781 pj => elp%pts(face_nodes(j,pf))%p
1782 if (norm2(pi%x(1:3) - pj%x(1:3) - l) .lt. tol)
then
1783 id = min(pi%id(), pj%id())
1786 p_local_idx = this%get_local(this%points(id))
1790 if ( match .gt. 1)
then
1791 call neko_error(
'Multiple matches when creating periodic ids')
1792 else if (match .eq. 0)
then
1793 call neko_error(
'Cannot find matching periodic point')
1798 select type(elp => this%elements(pe)%e)
1802 l = l + ele%pts(edge_nodes(i,f))%p%x(1:3) - &
1803 elp%pts(edge_nodes(i,pf))%p%x(1:3)
1807 pi => ele%pts(edge_nodes(i,f))%p
1809 pj => elp%pts(edge_nodes(j,pf))%p
1811 if (norm2(pi%x(1:3) - pj%x(1:3) - l) .lt. tol)
then
1812 id = min(pi%id(), pj%id())
1815 p_local_idx = this%get_local(this%points(id))
1826 class(
mesh_t),
intent(inout) :: this
1827 integer,
intent(in) :: f
1828 integer,
intent(in) :: e
1829 integer,
intent(in) :: pf
1830 integer,
intent(in) :: pe
1831 integer,
intent(inout) :: pids(4)
1833 integer :: i, id, p_local_idx
1836 integer,
dimension(4, 6) :: face_nodes = reshape([&
1844 select type(ele => this%elements(e)%e)
1847 pi => ele%pts(face_nodes(i,f))%p
1848 call pi%set_id(pids(i))
1849 call this%add_point(pi, id)
1850 p_local_idx = this%get_local(this%points(id))
1858 class(
mesh_t),
intent(inout) :: this
1859 type(
point_t),
intent(inout) :: p
1866 if (this%htp%get(tmp, local_id) .gt. 0)
then
1867 call neko_error(
'Invalid global id (local point)')
1875 class(
mesh_t),
intent(inout) :: this
1879 if (this%hte%get(e, local_id) .gt. 0)
then
1880 call neko_error(
'Invalid global id (local edge)')
1887 class(
mesh_t),
intent(inout) :: this
1891 if (this%htf%get(f, local_id) .gt. 0)
then
1892 call neko_error(
'Invalid global id (local facet)')
1899 class(
mesh_t),
intent(inout) :: this
1901 integer :: global_id
1903 global_id = this%get_local(e)
1905 if (this%gdim .eq. 2)
then
1907 global_id = this%ddata%local_to_global_facet(global_id)
1911 global_id = this%ddata%local_to_global_edge(global_id)
1919 class(
mesh_t),
intent(inout) :: this
1921 integer :: global_id
1923 global_id = this%get_local_facet(f)
1926 global_id = this%ddata%local_to_global_facet(global_id)
1936 class(
mesh_t),
intent(inout) :: this
1937 integer,
intent(inout) :: index
1940 if (this%htp%get(index, local_id) .eq. 1)
then
1949 class(
mesh_t),
intent(inout) :: this
1950 type(
point_t),
intent(inout) :: p
1951 integer :: local_index
1954 local_index = this%get_local(p)
1955 shared = this%ddata%shared_point%element(local_index)
1963 class(
mesh_t),
intent(inout) :: this
1965 integer :: local_index
1967 local_index = this%get_local(e)
1968 if (this%gdim .eq. 2)
then
1969 shared = this%ddata%shared_facet%element(local_index)
1971 shared = this%ddata%shared_edge%element(local_index)
1977 class(
mesh_t),
intent(inout) :: this
1979 integer :: local_index
1982 local_index = this%get_local(f)
1983 shared = this%ddata%shared_facet%element(local_index)
1990 class(
mesh_t),
intent(inout) :: this
1992 real(kind=
rp) :: v(8)
1998 if (this%gdim .eq. 3)
then
2001 this%elements(i)%e%pts(2)%p%x, &
2002 this%elements(i)%e%pts(3)%p%x, &
2003 this%elements(i)%e%pts(5)%p%x, &
2004 this%elements(i)%e%pts(1)%p%x &
2008 this%elements(i)%e%pts(4)%p%x, &
2009 this%elements(i)%e%pts(1)%p%x, &
2010 this%elements(i)%e%pts(6)%p%x, &
2011 this%elements(i)%e%pts(2)%p%x &
2015 this%elements(i)%e%pts(1)%p%x, &
2016 this%elements(i)%e%pts(4)%p%x, &
2017 this%elements(i)%e%pts(7)%p%x, &
2018 this%elements(i)%e%pts(3)%p%x &
2022 this%elements(i)%e%pts(3)%p%x, &
2023 this%elements(i)%e%pts(2)%p%x, &
2024 this%elements(i)%e%pts(8)%p%x, &
2025 this%elements(i)%e%pts(4)%p%x &
2029 this%elements(i)%e%pts(6)%p%x, &
2030 this%elements(i)%e%pts(7)%p%x, &
2031 this%elements(i)%e%pts(1)%p%x, &
2032 this%elements(i)%e%pts(5)%p%x &
2036 this%elements(i)%e%pts(8)%p%x, &
2037 this%elements(i)%e%pts(5)%p%x, &
2038 this%elements(i)%e%pts(2)%p%x, &
2039 this%elements(i)%e%pts(6)%p%x &
2043 this%elements(i)%e%pts(5)%p%x, &
2044 this%elements(i)%e%pts(8)%p%x, &
2045 this%elements(i)%e%pts(3)%p%x, &
2046 this%elements(i)%e%pts(7)%p%x &
2050 this%elements(i)%e%pts(7)%p%x, &
2051 this%elements(i)%e%pts(6)%p%x, &
2052 this%elements(i)%e%pts(4)%p%x, &
2053 this%elements(i)%e%pts(8)%p%x &
2056 if (v(1) .le. 0.0_rp .or. &
2057 v(2) .le. 0.0_rp .or. &
2058 v(3) .le. 0.0_rp .or. &
2059 v(4) .le. 0.0_rp .or. &
2060 v(5) .le. 0.0_rp .or. &
2061 v(6) .le. 0.0_rp .or. &
2062 v(7) .le. 0.0_rp .or. &
2063 v(8) .le. 0.0_rp )
then
2065 centroid = this%elements(i)%e%centroid()
2067 write(error_unit,
'(A, A, I0, A, 3G12.5)')
"*** ERROR ***: ", &
2068 "Wrong orientation of mesh element ", i, &
2069 " with centroid ", centroid%x
2077 call neko_error(
"Some mesh elements are not right-handed")
2090 real(kind=
dp),
dimension(3),
intent(in) :: p1, p2, p3, origin
2092 real(kind=
dp) :: vp1(3), vp2(3), vp3(3), cross(3)
2098 cross(1) = vp1(2)*vp2(3) - vp2(3)*vp1(2)
2099 cross(2) = vp1(3)*vp2(1) - vp1(1)*vp2(3)
2100 cross(3) = vp1(1)*vp2(2) - vp1(2)*vp2(1)
2102 v = cross(1)*vp3(1) + cross(2)*vp3(2) + cross(3)*vp3(3)
2116 class(
mesh_t),
intent(in) :: this
2117 class(
mesh_t),
intent(inout) :: other
2118 type(
mask_t),
intent(in) :: mask
2119 integer,
intent(in) :: lx, ly, lz
2120 integer :: i, j, k, nelv, lxyz, gdim, e_m, nidx(4), nelv_c, el_c, el, i_m
2128 nelv =
mask%size()/lxyz
2129 call other%init(this%gdim, nelv)
2132 if (other%gdim .eq. 2)
then
2133 call neko_error(
"Subset mesh not implemented for 2d")
2134 else if (other%gdim .eq. 3)
then
2136 i_m = 1 + lxyz * (el - 1)
2147 call p(j)%init(this%elements(e_m)%e%pts(j)%p%x, p_id)
2151 call other%add_element(el, el + other%offset_el, &
2152 p(1), p(2), p(3), p(4), &
2153 p(5), p(6), p(7), p(8))
2162 nelv_c = this%curve%size
2163 if (nelv_c .gt. 0)
then
2167 do while (el .le. nelv .and. el_c .le. nelv_c)
2169 i_m = 1 + lxyz * (el - 1)
2173 if (e_m .lt. this%curve%curve_el(el_c)%el_idx)
then
2176 else if (e_m .gt. this%curve%curve_el(el_c)%el_idx)
then
2180 call other%mark_curve_element(el, &
2181 this%curve%curve_el(el_c)%curve_data, &
2182 this%curve%curve_el(el_c)%curve_type)
2191 call other%finalize()
2193 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.