51 use mpi_f08,
only : mpi_integer, mpi_max, mpi_sum, mpi_in_place, &
52 mpi_allreduce, mpi_exscan, mpi_request, mpi_status, mpi_wait, &
53 mpi_isend, mpi_irecv, mpi_status_ignore, mpi_integer8, &
54 mpi_get_count, mpi_sendrecv
58 use,
intrinsic :: iso_fortran_env, only: error_unit
89 logical,
allocatable :: dfrmd_el(:)
97 integer,
allocatable :: facet_neigh(:,:)
106 logical,
allocatable :: neigh(:)
107 integer,
allocatable :: neigh_order(:)
109 integer(2),
allocatable :: facet_type(:,:)
115 logical :: lconn = .false.
116 logical :: ldist = .false.
117 logical :: lnumr = .false.
118 logical :: lgenc = .true.
122 procedure(
mesh_deform), pass(msh),
pointer :: apply_deform => null()
153 procedure, pass(this) :: check_right_handedness => &
156 generic :: init => init_nelv, init_dist
158 generic :: add_element => add_quad, add_hex
161 generic :: get_local => get_local_point, get_local_edge, get_local_facet
164 generic :: get_global => get_global_edge, get_global_facet
166 generic :: is_shared => is_shared_point, is_shared_edge, is_shared_facet
174 integer,
intent(in) :: lx, ly, lz
175 real(kind=
rp),
intent(inout) :: x(lx, ly, lz, msh%nelv)
176 real(kind=
rp),
intent(inout) :: y(lx, ly, lz, msh%nelv)
177 real(kind=
rp),
intent(inout) :: z(lx, ly, lz, msh%nelv)
188 class(
mesh_t),
intent(inout) :: this
189 integer,
intent(in) :: gdim
190 integer,
intent(in) :: nelv
192 character(len=LOG_SIZE) :: log_buf
199 if (this%nelv < 1)
then
200 write(log_buf,
'(A,I0,A)')
'MPI rank ',
pe_rank,
' has zero elements'
204 call mpi_allreduce(this%nelv, this%glb_nelv, 1, &
208 call mpi_exscan(this%nelv, this%offset_el, 1, &
217 class(
mesh_t),
intent(inout) :: this
218 integer,
intent(in) :: gdim
220 character(len=LOG_SIZE) :: log_buf
224 this%nelv = dist%num_local()
225 if (this%nelv < 1)
then
226 write(log_buf,
'(A,I0,A)')
'MPI rank ',
pe_rank,
' has zero elements'
229 this%glb_nelv = dist%num_global()
230 this%offset_el = dist%start_idx()
238 type(
mesh_t),
intent(inout) :: this
244 allocate(this%elements(this%nelv))
245 allocate(this%dfrmd_el(this%nelv))
246 if (this%gdim .eq. 3)
then
248 allocate(
hex_t::this%elements(i)%e)
254 select type (fmp => this%facet_map)
256 call fmp%init(this%nelv, facet_data)
264 else if (this%gdim .eq. 2)
then
266 allocate(
quad_t::this%elements(i)%e)
271 select type (fmp => this%facet_map)
273 call fmp%init(this%nelv, facet_data)
285 allocate(this%points(this%npts*this%nelv))
291 if (
allocated(this%point_neigh))
then
292 deallocate(this%point_neigh)
294 allocate(this%point_neigh(this%gdim*this%npts*this%nelv))
295 do i = 1, this%gdim*this%npts*this%nelv
296 call this%point_neigh(i)%init()
300 allocate(this%facet_type(2 * this%gdim, this%nelv))
303 call this%htp%init(this%npts*this%nelv, i)
304 call this%htel%init(this%nelv, i)
306 call this%periodic%init(this%nelv)
310 call this%labeled_zones(i)%init(this%nelv)
313 call this%curve%init(this%nelv)
315 call this%ddata%init()
317 allocate(this%neigh(0:
pe_size-1))
328 class(
mesh_t),
intent(inout) :: this
334 call this%htel%free()
335 call this%ddata%free()
336 call this%curve%free()
338 if (
allocated(this%dfrmd_el))
then
339 deallocate(this%dfrmd_el)
342 if (
allocated(this%elements))
then
344 call this%elements(i)%e%free()
345 deallocate(this%elements(i)%e)
347 deallocate(this%elements)
350 if (
allocated(this%facet_map))
then
351 select type (fmp => this%facet_map)
357 deallocate(this%facet_map)
360 if (
allocated(this%facet_neigh))
then
361 deallocate(this%facet_neigh)
364 if (
allocated(this%point_neigh))
then
365 do i = 1, this%gdim * this%npts * this%nelv
366 call this%point_neigh(i)%free()
372 if (
allocated(this%facet_type))
then
373 deallocate(this%facet_type)
375 if (
allocated(this%labeled_zones))
then
377 call this%labeled_zones(i)%free()
379 deallocate(this%labeled_zones)
382 if (
allocated(this%neigh))
then
383 deallocate(this%neigh)
386 if (
allocated(this%neigh_order))
then
387 deallocate(this%neigh_order)
390 if (
allocated(this%points))
then
391 deallocate(this%points)
394 call this%periodic%free()
403 class(
mesh_t),
target,
intent(inout) :: this
409 call this%periodic%finalize()
411 call this%labeled_zones(i)%finalize()
413 call this%curve%finalize()
421 type(
mesh_t),
intent(inout) :: this
422 real(kind=
dp) :: u(3), v(3), w(3), temp
426 if (this%gdim .eq. 2)
then
427 this%dfrmd_el(e) = .false.
428 u = this%elements(e)%e%pts(2)%p%x - this%elements(e)%e%pts(1)%p%x
429 v = this%elements(e)%e%pts(3)%p%x - this%elements(e)%e%pts(1)%p%x
430 temp = u(1)*v(1) + u(2)*v(2)
431 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
433 this%dfrmd_el(e) = .false.
434 u = this%elements(e)%e%pts(2)%p%x - this%elements(e)%e%pts(1)%p%x
435 v = this%elements(e)%e%pts(3)%p%x - this%elements(e)%e%pts(1)%p%x
436 w = this%elements(e)%e%pts(5)%p%x - this%elements(e)%e%pts(1)%p%x
437 temp = u(1)*v(1) + u(2)*v(2) + u(3)*v(3)
438 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
439 temp = u(1)*w(1) + u(2)*w(2) + u(3)*w(3)
440 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
441 u = this%elements(e)%e%pts(7)%p%x - this%elements(e)%e%pts(8)%p%x
442 v = this%elements(e)%e%pts(6)%p%x - this%elements(e)%e%pts(8)%p%x
443 w = this%elements(e)%e%pts(4)%p%x - this%elements(e)%e%pts(8)%p%x
444 temp = u(1)*v(1) + u(2)*v(2) + u(3)*v(3)
445 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
446 temp = u(1)*w(1) + u(2)*w(2) + u(3)*w(3)
447 if(.not.
abscmp(temp, 0d0)) this%dfrmd_el(e) = .true.
454 class(
mesh_t),
intent(inout) :: this
455 this%dfrmd_el = .true.
460 class(
mesh_t),
target,
intent(inout) :: this
468 integer :: p_local_idx
470 integer :: i, j, k, ierr, el_glb_idx, n_sides, n_nodes, src, dst
472 if (this%lconn)
return
474 if (.not. this%lgenc)
return
478 ep => this%elements(el)%e
483 call this%add_point(ep%pts(i)%p, id)
484 p_local_idx = this%get_local(this%points(id))
487 call this%point_neigh(p_local_idx)%push(id)
490 call ep%facet_id(f, i)
491 call this%add_face(f)
495 call ep%edge_id(e, i)
496 call this%add_edge(e)
501 call this%add_point(ep%pts(i)%p, id)
502 p_local_idx = this%get_local(this%points(id))
505 call this%point_neigh(p_local_idx)%push(id)
509 call ep%facet_id(e, i)
510 call this%add_edge(e)
516 if (this%gdim .eq. 2)
then
525 call mpi_allreduce(this%max_pts_id, this%glb_mpts, 1, &
535 select type (fmp => this%facet_map)
539 el_glb_idx = i + this%offset_el
541 call this%elements(i)%e%facet_id(edge, j)
544 facet_data%x = [0, 0]
547 if (fmp%get(edge, facet_data) .eq. 0)
then
549 if (facet_data%x(1) .eq. el_glb_idx )
then
550 this%facet_neigh(j, i) = facet_data%x(2)
551 else if( facet_data%x(2) .eq. el_glb_idx)
then
552 this%facet_neigh(j, i) = facet_data%x(1)
554 else if(facet_data%x(1) .gt. el_glb_idx)
then
555 facet_data%x(2) = facet_data%x(1)
556 facet_data%x(1) = el_glb_idx
557 this%facet_neigh(j, i) = facet_data%x(2)
558 call fmp%set(edge, facet_data)
559 else if(facet_data%x(1) .lt. el_glb_idx)
then
560 facet_data%x(2) = el_glb_idx
561 this%facet_neigh(j, i) = facet_data%x(1)
562 call fmp%set(edge, facet_data)
565 facet_data%x(1) = el_glb_idx
566 this%facet_neigh(j, i) = facet_data%x(2)
567 call fmp%set(edge, facet_data)
576 el_glb_idx = i + this%offset_el
578 call this%elements(i)%e%facet_id(face, j)
580 facet_data%x = (/ 0, 0/)
583 if (fmp%get(face, facet_data) .eq. 0)
then
585 if (facet_data%x(1) .eq. el_glb_idx )
then
586 this%facet_neigh(j, i) = facet_data%x(2)
587 call this%elements(i)%e%facet_id(face_comp, &
588 j + (2*mod(j, 2) - 1))
589 if (face_comp .eq. face)
then
590 facet_data%x(2) = el_glb_idx
591 this%facet_neigh(j, i) = facet_data%x(1)
592 call fmp%set(face, facet_data)
594 else if( facet_data%x(2) .eq. el_glb_idx)
then
595 this%facet_neigh(j, i) = facet_data%x(1)
597 else if(facet_data%x(1) .gt. el_glb_idx)
then
598 facet_data%x(2) = facet_data%x(1)
599 facet_data%x(1) = el_glb_idx
600 this%facet_neigh(j, i) = facet_data%x(2)
601 call fmp%set(face, facet_data)
602 else if(facet_data%x(1) .lt. el_glb_idx)
then
603 facet_data%x(2) = el_glb_idx
604 this%facet_neigh(j, i) = facet_data%x(1)
605 call fmp%set(face, facet_data)
608 facet_data%x(1) = el_glb_idx
609 this%facet_neigh(j, i) = 0
610 call fmp%set(face, facet_data)
635 if (this%neigh(src) .or. this%neigh(dst))
then
637 call neigh_order%push(j)
641 allocate(this%neigh_order(neigh_order%size()))
642 select type(order => neigh_order%data)
644 do i = 1, neigh_order%size()
645 this%neigh_order(i) = order(i)
648 call neigh_order%free()
652 allocate(this%neigh_order(1))
661 if (this%gdim .eq. 3)
then
674 type(
mesh_t),
intent(inout) :: this
679 type(mpi_status) :: status
680 type(mpi_request) :: send_req, recv_req
681 integer,
allocatable :: recv_buffer(:)
682 integer :: i, j, k, el_glb_idx, n_sides, n_nodes, facet, element, l
683 integer :: max_recv, ierr, src, dst, n_recv, recv_side, neigh_el
686 if (this%gdim .eq. 2)
then
699 el_glb_idx = i + this%offset_el
702 if (this%facet_neigh(j, i) .eq. 0)
then
703 if (n_nodes .eq. 2)
then
704 call this%elements(i)%e%facet_id(edge, j)
705 call buffer%push(el_glb_idx)
708 call buffer%push(edge%x(k))
711 call this%elements(i)%e%facet_id(face, j)
712 call buffer%push(el_glb_idx)
715 call buffer%push(face%x(k))
723 call mpi_allreduce(
buffer%size(), max_recv, 1, &
726 allocate(recv_buffer(max_recv))
728 do i = 1,
size(this%neigh_order)
732 if (this%neigh(src))
then
733 call mpi_irecv(recv_buffer, max_recv, mpi_integer, &
737 if (this%neigh(dst))
then
738 call mpi_isend(
buffer%array(),
buffer%size(), mpi_integer, &
742 if (this%neigh(src))
then
743 call mpi_wait(recv_req, status, ierr)
744 call mpi_get_count(status, mpi_integer, n_recv, ierr)
746 select type (fmp => this%facet_map)
748 do j = 1, n_recv, n_nodes + 2
749 neigh_el = recv_buffer(j)
750 recv_side = recv_buffer(j+1)
752 edge = (/ recv_buffer(j+2), recv_buffer(j+3) /)
754 facet_data = (/ 0, 0 /)
756 if (fmp%get(edge, facet_data) .eq. 0)
then
757 element = facet_data%x(1) - this%offset_el
760 call this%elements(
element)%e%facet_id(edge2, l)
761 if(edge2 .eq. edge)
then
766 this%facet_neigh(facet,
element) = -neigh_el
767 facet_data%x(2) = -neigh_el
770 call fmp%set(edge, facet_data)
772 call this%ddata%set_shared_el_facet(
element, facet)
774 if (this%hte%get(edge, facet) .eq. 0)
then
775 call this%ddata%set_shared_facet(facet)
784 do j = 1, n_recv, n_nodes + 2
785 neigh_el = recv_buffer(j)
786 recv_side = recv_buffer(j+1)
788 face%x = (/ recv_buffer(j+2), recv_buffer(j+3), &
789 recv_buffer(j+4), recv_buffer(j+5) /)
792 facet_data%x = (/ 0, 0 /)
795 if (fmp%get(face, facet_data) .eq. 0)
then
797 element = facet_data%x(1) - this%offset_el
799 call this%elements(
element)%e%facet_id(face2, l)
800 if(face2 .eq. face)
then
805 this%facet_neigh(facet,
element) = -neigh_el
806 facet_data%x(2) = -neigh_el
809 call fmp%set(face, facet_data)
811 call this%ddata%set_shared_el_facet(
element, facet)
813 if (this%htf%get(face, facet) .eq. 0)
then
814 call this%ddata%set_shared_facet(facet)
826 if (this%neigh(dst))
then
827 call mpi_wait(send_req, mpi_status_ignore, ierr)
833 deallocate(recv_buffer)
841 type(
mesh_t),
intent(inout) :: this
843 type(mpi_status) :: status
844 integer,
allocatable :: recv_buffer(:)
846 integer :: max_recv, ierr, src, dst, n_recv, neigh_el
847 integer :: pt_glb_idx, pt_loc_idx, num_neigh
848 integer,
contiguous,
pointer :: neighs(:)
851 call send_buffer%init(this%mpts * 2)
856 pt_glb_idx = this%points(i)%id()
857 num_neigh = this%point_neigh(i)%size()
858 call send_buffer%push(pt_glb_idx)
859 call send_buffer%push(num_neigh)
861 neighs => this%point_neigh(i)%array()
862 do j = 1, this%point_neigh(i)%size()
863 call send_buffer%push(neighs(j))
867 call mpi_allreduce(send_buffer%size(), max_recv, 1, &
869 allocate(recv_buffer(max_recv))
875 call mpi_sendrecv(send_buffer%array(), send_buffer%size(), &
876 mpi_integer, dst, 0, recv_buffer, max_recv, mpi_integer, src, 0, &
879 call mpi_get_count(status, mpi_integer, n_recv, ierr)
882 do while (j .le. n_recv)
883 pt_glb_idx = recv_buffer(j)
884 num_neigh = recv_buffer(j + 1)
886 pt_loc_idx = this%have_point_glb_idx(pt_glb_idx)
887 if (pt_loc_idx .gt. 0)
then
888 this%neigh(src) = .true.
890 neigh_el = -recv_buffer(j + 1 + k)
891 call this%point_neigh(pt_loc_idx)%push(neigh_el)
892 call this%ddata%set_shared_point(pt_loc_idx)
895 j = j + (2 + num_neigh)
900 deallocate(recv_buffer)
901 call send_buffer%free()
909 type(
mesh_t),
target,
intent(inout) :: this
912 type(
uset_i8_t),
target :: edge_idx, ghost, owner
915 type(mpi_status) :: status
916 type(mpi_request) :: send_req, recv_req
917 integer,
contiguous,
pointer :: p1(:), p2(:), ns_id(:)
918 integer :: i, j, id, ierr, num_edge_glb, edge_offset, num_edge_loc
919 integer :: k, l , shared_offset, glb_nshared, n_glb_id
920 integer(kind=i8) :: C, glb_max, glb_id
921 integer(kind=i8),
pointer :: glb_ptr
922 integer(kind=i8),
allocatable :: recv_buff(:)
923 logical :: shared_edge
925 integer :: max_recv, src, dst, n_recv
929 allocate(this%ddata%local_to_global_edge(this%meds))
931 call edge_idx%init(this%hte%num_entries())
932 call send_buff%init(this%hte%num_entries())
933 call owner%init(this%hte%num_entries())
935 call glb_to_loc%init(32, i)
943 num_edge_glb = 2* this%meds
944 call mpi_allreduce(mpi_in_place, num_edge_glb, 1, &
947 glb_max = int(num_edge_glb,
i8)
949 call non_shared_edges%init(this%hte%num_entries())
951 call it%init(this%hte)
956 k = this%have_point_glb_idx(edge%x(1))
957 l = this%have_point_glb_idx(edge%x(2))
958 p1 => this%point_neigh(k)%array()
959 p2 => this%point_neigh(l)%array()
961 shared_edge = .false.
964 do i = 1, this%point_neigh(k)%size()
965 do j = 1, this%point_neigh(l)%size()
966 if ((p1(i) .eq. p2(j)) .and. &
967 (p1(i) .lt. 0) .and. (p2(j) .lt. 0))
then
968 call this%ddata%set_shared_edge(id)
977 if (shared_edge)
then
978 glb_id = ((int(edge%x(1),
i8)) + int(edge%x(2),
i8)*c) + glb_max
979 call glb_to_loc%set(glb_id, id)
980 call edge_idx%add(glb_id)
981 call owner%add(glb_id)
982 call send_buff%push(glb_id)
984 call non_shared_edges%push(id)
990 num_edge_loc = non_shared_edges%size()
991 call mpi_exscan(num_edge_loc, edge_offset, 1, &
993 edge_offset = edge_offset + 1
996 ns_id => non_shared_edges%array()
997 do i = 1, non_shared_edges%size()
998 call this%ddata%set_local_to_global_edge(ns_id(i), edge_offset)
999 edge_offset = edge_offset + 1
1007 call mpi_allreduce(send_buff%size(), max_recv, 1, &
1010 call ghost%init(send_buff%size())
1012 allocate(recv_buff(max_recv))
1014 do i = 1,
size(this%neigh_order)
1018 if (this%neigh(src))
then
1019 call mpi_irecv(recv_buff, max_recv, mpi_integer8, &
1023 if (this%neigh(dst))
then
1027 select type(sbarray=>send_buff%data)
1028 type is (
integer(i8))
1029 call mpi_isend(sbarray, send_buff%size(), mpi_integer8, &
1034 if (this%neigh(src))
then
1035 call mpi_wait(recv_req, status, ierr)
1036 call mpi_get_count(status, mpi_integer8, n_recv, ierr)
1039 if ((edge_idx%element(recv_buff(j))) .and. (src .lt.
pe_rank))
then
1040 call ghost%add(recv_buff(j))
1041 call owner%remove(recv_buff(j))
1046 if (this%neigh(dst))
then
1047 call mpi_wait(send_req, mpi_status_ignore, ierr)
1053 glb_nshared = num_edge_loc
1054 call mpi_allreduce(mpi_in_place, glb_nshared, 1, &
1058 call mpi_exscan(owner%size(), shared_offset, 1, &
1060 shared_offset = shared_offset + glb_nshared + 1
1063 call send_buff%clear()
1064 call owner%iter_init()
1065 do while (owner%iter_next())
1066 glb_ptr => owner%iter_value()
1067 if (glb_to_loc%get(glb_ptr, id) .eq. 0)
then
1068 call this%ddata%set_local_to_global_edge(id, shared_offset)
1071 call send_buff%push(glb_ptr)
1072 glb_id = int(shared_offset, i8)
1073 call send_buff%push(glb_id)
1075 shared_offset = shared_offset + 1
1084 this%glb_meds = shared_offset -1
1085 call mpi_allreduce(mpi_in_place, this%glb_meds, 1, &
1092 call mpi_allreduce(send_buff%size(), max_recv, 1, &
1095 deallocate(recv_buff)
1096 allocate(recv_buff(max_recv))
1099 do i = 1,
size(this%neigh_order)
1103 if (this%neigh(src))
then
1104 call mpi_irecv(recv_buff, max_recv, mpi_integer8, &
1108 if (this%neigh(dst))
then
1112 select type(sbarray=>send_buff%data)
1113 type is (
integer(i8))
1114 call mpi_isend(sbarray, send_buff%size(), mpi_integer8, &
1119 if (this%neigh(src))
then
1120 call mpi_wait(recv_req, status, ierr)
1121 call mpi_get_count(status, mpi_integer8, n_recv, ierr)
1124 if (ghost%element(recv_buff(j)))
then
1125 if (glb_to_loc%get(recv_buff(j), id) .eq. 0)
then
1126 n_glb_id = int(recv_buff(j + 1 ), 4)
1127 call this%ddata%set_local_to_global_edge(id, n_glb_id)
1135 if (this%neigh(dst))
then
1136 call mpi_wait(send_req, mpi_status_ignore, ierr)
1140 deallocate(recv_buff)
1141 call glb_to_loc%free()
1142 call send_buff%free()
1143 call edge_idx%free()
1144 call non_shared_edges%free()
1152 type(
mesh_t),
target,
intent(inout) :: this
1165 type(mpi_status) :: status
1166 type(mpi_request) :: send_req, recv_req
1167 integer,
allocatable :: recv_buff(:)
1168 integer :: non_shared_facets, shared_facets, facet_offset
1169 integer :: id, glb_nshared, shared_offset, owned_facets
1170 integer :: i, j, ierr, max_recv, src, dst, n_recv
1172 shared_facets = this%ddata%shared_facet%size()
1175 if (this%gdim .eq. 2)
then
1176 allocate(this%ddata%local_to_global_facet(this%meds))
1177 call edge_owner%init(this%meds)
1178 call edge_ghost%init(64, i)
1179 non_shared_facets = this%hte%num_entries() - shared_facets
1181 allocate(this%ddata%local_to_global_facet(this%mfcs))
1182 call face_owner%init(this%mfcs)
1183 call face_ghost%init(64, i)
1184 non_shared_facets = this%htf%num_entries() - shared_facets
1190 call mpi_exscan(non_shared_facets, facet_offset, 1, &
1192 facet_offset = facet_offset + 1
1195 if (this%gdim .eq. 2)
then
1196 call edge_it%init(this%hte)
1197 do while (edge_it%next())
1198 call edge_it%data(id)
1199 edge => edge_it%key()
1200 if (.not. this%ddata%shared_facet%element(id))
then
1201 call this%ddata%set_local_to_global_facet(id, facet_offset)
1202 facet_offset = facet_offset + 1
1204 select type(fmp => this%facet_map)
1206 if (fmp%get(edge, facet_data) .eq. 0)
then
1207 if (facet_data%x(2) .lt. 0)
then
1208 if (abs(facet_data%x(2)) .lt. (this%offset_el + 1))
then
1209 call edge_ghost%set(edge, id)
1211 call edge_owner%push(edge)
1220 owned_facets = edge_owner%size()
1222 call face_it%init(this%htf)
1223 do while (face_it%next())
1224 call face_it%data(id)
1225 face => face_it%key()
1226 if (.not. this%ddata%shared_facet%element(id))
then
1227 call this%ddata%set_local_to_global_facet(id, facet_offset)
1228 facet_offset = facet_offset + 1
1230 select type(fmp => this%facet_map)
1232 if (fmp%get(face, facet_data) .eq. 0)
then
1233 if (facet_data%x(2) .lt. 0)
then
1234 if (abs(facet_data%x(2)) .lt. (this%offset_el + 1))
then
1235 call face_ghost%set(face, id)
1237 call face_owner%push(face)
1246 owned_facets = face_owner%size()
1250 glb_nshared = non_shared_facets
1251 call mpi_allreduce(mpi_in_place, glb_nshared, 1, &
1255 call mpi_exscan(owned_facets, shared_offset, 1, &
1257 shared_offset = shared_offset + glb_nshared + 1
1259 if (this%gdim .eq. 2)
then
1261 if (owned_facets .gt. 32)
then
1262 call send_buff%init(owned_facets)
1264 call send_buff%init()
1267 ed => edge_owner%array()
1268 do i = 1, edge_owner%size()
1269 if (this%hte%get(ed(i), id) .eq. 0)
then
1270 call this%ddata%set_local_to_global_facet(id, shared_offset)
1275 call send_buff%push(ed(i)%x(j))
1277 call send_buff%push(shared_offset)
1279 shared_offset = shared_offset + 1
1285 if (owned_facets .gt. 32)
then
1286 call send_buff%init(owned_facets)
1288 call send_buff%init()
1291 fd => face_owner%array()
1292 do i = 1, face_owner%size()
1293 if (this%htf%get(fd(i), id) .eq. 0)
then
1294 call this%ddata%set_local_to_global_facet(id, shared_offset)
1299 call send_buff%push(fd(i)%x(j))
1301 call send_buff%push(shared_offset)
1303 shared_offset = shared_offset + 1
1312 this%glb_mfcs = shared_offset - 1
1313 call mpi_allreduce(mpi_in_place, this%glb_mfcs, 1, &
1320 call mpi_allreduce(send_buff%size(), max_recv, 1, &
1323 allocate(recv_buff(max_recv))
1326 do i = 1,
size(this%neigh_order)
1330 if (this%neigh(src))
then
1331 call mpi_irecv(recv_buff, max_recv, mpi_integer, &
1335 if (this%neigh(dst))
then
1336 call mpi_isend(send_buff%array(), send_buff%size(), mpi_integer, &
1340 if (this%neigh(src))
then
1341 call mpi_wait(recv_req, status, ierr)
1342 call mpi_get_count(status, mpi_integer, n_recv, ierr)
1344 if (this%gdim .eq. 2)
then
1347 recv_edge = (/recv_buff(j), recv_buff(j+1)/)
1350 if (edge_ghost%get(recv_edge, id) .eq. 0)
then
1351 call this%ddata%set_local_to_global_facet(id, recv_buff(j+2))
1357 recv_face = (/recv_buff(j), recv_buff(j+1), &
1358 recv_buff(j+2), recv_buff(j+3) /)
1361 if (face_ghost%get(recv_face, id) .eq. 0)
then
1362 call this%ddata%set_local_to_global_facet(id, recv_buff(j+4))
1368 if (this%neigh(dst))
then
1369 call mpi_wait(send_req, mpi_status_ignore, ierr)
1374 if (this%gdim .eq. 2)
then
1375 call edge_owner%free()
1376 call edge_ghost%free()
1378 call face_owner%free()
1379 call face_ghost%free()
1382 call send_buff%free()
1383 deallocate(recv_buff)
1390 class(
mesh_t),
target,
intent(inout) :: this
1391 integer,
value :: el, el_glb
1392 type(
point_t),
target,
intent(inout) :: p1, p2, p3, p4
1397 this%lconn = .false.
1400 this%lnumr = .false.
1402 call this%add_point(p1, p(1))
1403 call this%add_point(p2, p(2))
1404 call this%add_point(p3, p(3))
1405 call this%add_point(p4, p(4))
1407 select type (ep => this%elements(el)%e)
1409 call ep%init(el_glb, &
1410 this%points(p(1)), this%points(p(2)), &
1411 this%points(p(3)), this%points(p(4)))
1421 subroutine mesh_add_hex(this, el, el_glb, p1, p2, p3, p4, p5, p6, p7, p8)
1422 class(
mesh_t),
target,
intent(inout) :: this
1423 integer,
value :: el, el_glb
1424 type(
point_t),
target,
intent(inout) :: p1, p2, p3, p4, p5, p6, p7, p8
1430 this%lconn = .false.
1433 this%lnumr = .false.
1435 call this%add_point(p1, p(1))
1436 call this%add_point(p2, p(2))
1437 call this%add_point(p3, p(3))
1438 call this%add_point(p4, p(4))
1439 call this%add_point(p5, p(5))
1440 call this%add_point(p6, p(6))
1441 call this%add_point(p7, p(7))
1442 call this%add_point(p8, p(8))
1445 call this%htel%set(el_glb, el)
1447 select type (ep => this%elements(el)%e)
1449 call ep%init(el_glb, &
1450 this%points(p(1)), this%points(p(2)), &
1451 this%points(p(3)), this%points(p(4)), &
1452 this%points(p(5)), this%points(p(6)), &
1453 this%points(p(7)), this%points(p(8)))
1462 class(
mesh_t),
intent(inout) :: this
1463 type(
point_t),
intent(inout) :: p
1464 integer,
intent(inout) :: idx
1469 this%max_pts_id =
max(this%max_pts_id, tmp)
1471 if (tmp .le. 0)
then
1475 if (this%htp%get(tmp, idx) .gt. 0)
then
1476 this%mpts = this%mpts + 1
1477 call this%htp%set(tmp, this%mpts)
1478 this%points(this%mpts) = p
1486 class(
mesh_t),
intent(inout) :: this
1490 if (this%htf%get(f, idx) .gt. 0)
then
1491 this%mfcs = this%mfcs + 1
1492 call this%htf%set(f, this%mfcs)
1499 class(
mesh_t),
intent(inout) :: this
1503 if (this%hte%get(e, idx) .gt. 0)
then
1504 this%meds = this%meds + 1
1505 call this%hte%set(e, this%meds)
1512 class(
mesh_t),
intent(inout) :: this
1513 integer,
intent(in) :: e
1514 real(kind=
dp),
dimension(5,12),
intent(in) :: curve_data
1515 integer,
dimension(12),
intent(in) :: curve_type
1517 if (e .gt. this%nelv)
then
1520 if ((this%gdim .eq. 2 .and. sum(curve_type(5:8)) .gt. 0) )
then
1523 call this%curve%add_element(e, curve_data, curve_type)
1529 class(
mesh_t),
intent(inout) :: this
1530 integer,
intent(in) :: f
1531 integer,
intent(in) :: e
1532 integer,
intent(in) :: label
1534 if (e .gt. this%nelv)
then
1538 if ((this%gdim .eq. 2 .and. f .gt. 4) .or. &
1539 (this%gdim .eq. 3 .and. f .gt. 6))
then
1542 call this%labeled_zones(label)%add_facet(f, e)
1543 this%facet_type(f,e) = -label
1549 class(
mesh_t),
intent(inout) :: this
1550 integer,
intent(in) :: f
1551 integer,
intent(in) :: e
1552 integer,
intent(in) :: pf
1553 integer,
intent(in) :: pe
1554 integer,
intent(inout) :: pids(4)
1555 integer,
dimension(4) :: org_ids
1557 call this%get_facet_ids(f, e, org_ids)
1558 call this%periodic%add_periodic_facet(f, e, pf, pe, pids, org_ids)
1563 class(
mesh_t),
intent(inout) :: this
1564 integer,
intent(in) :: f
1565 integer,
intent(in) :: e
1566 integer,
intent(inout) :: pids(4)
1571 select type(ele => this%elements(e)%e)
1573 call ele%facet_order(t,f)
1576 call ele%facet_order(t2,f)
1586 class(
mesh_t),
intent(inout) :: this
1592 integer :: org_ids(4), pids(4)
1594 integer,
dimension(4, 6) :: face_nodes = reshape([ &
1602 integer,
dimension(2, 4) :: edge_nodes = reshape([ &
1609 do i = 1, this%periodic%size
1610 e = this%periodic%facet_el(i)%x(2)
1611 f = this%periodic%facet_el(i)%x(1)
1612 pe = this%periodic%p_facet_el(i)%x(2)
1613 pf = this%periodic%p_facet_el(i)%x(1)
1614 pids = this%periodic%p_ids(i)%x
1615 call this%get_facet_ids(f, e, pids)
1616 this%periodic%p_ids(i)%x = pids
1618 do i = 1, this%periodic%size
1619 e = this%periodic%facet_el(i)%x(2)
1620 f = this%periodic%facet_el(i)%x(1)
1621 org_ids = this%periodic%org_ids(i)%x
1622 select type(ele => this%elements(e)%e)
1625 pi => ele%pts(face_nodes(j,f))%p
1626 call pi%set_id(org_ids(j))
1630 pi => ele%pts(edge_nodes(j,f))%p
1631 call pi%set_id(org_ids(j))
1639 class(
mesh_t),
intent(inout) :: this
1640 integer,
intent(in) :: f
1641 integer,
intent(in) :: e
1642 integer,
intent(in) :: pf
1643 integer,
intent(in) :: pe
1644 type(
point_t),
pointer :: pi, pj
1645 real(kind=
dp) :: l(3)
1646 integer :: i, j, id, p_local_idx, match
1649 integer,
dimension(4, 6) :: face_nodes = reshape([&
1657 integer,
dimension(2, 4) :: edge_nodes = reshape([&
1664 select type(ele => this%elements(e)%e)
1666 select type(elp => this%elements(pe)%e)
1670 l = l + ele%pts(face_nodes(i,f))%p%x(1:3) - &
1671 elp%pts(face_nodes(i,pf))%p%x(1:3)
1675 pi => ele%pts(face_nodes(i,f))%p
1678 pj => elp%pts(face_nodes(j,pf))%p
1679 if (norm2(pi%x(1:3) - pj%x(1:3) - l) .lt. 1d-7)
then
1680 id = min(pi%id(), pj%id())
1683 p_local_idx = this%get_local(this%points(id))
1687 if ( match .gt. 1)
then
1688 call neko_error(
'Multiple matches when creating periodic ids')
1689 else if (match .eq. 0)
then
1690 call neko_error(
'Cannot find matching periodic point')
1695 select type(elp => this%elements(pe)%e)
1699 l = l + ele%pts(edge_nodes(i,f))%p%x(1:3) - &
1700 elp%pts(edge_nodes(i,pf))%p%x(1:3)
1704 pi => ele%pts(edge_nodes(i,f))%p
1706 pj => elp%pts(edge_nodes(j,pf))%p
1708 if (norm2(pi%x(1:3) - pj%x(1:3) - l) .lt. 1d-7)
then
1709 id = min(pi%id(), pj%id())
1712 p_local_idx = this%get_local(this%points(id))
1723 class(
mesh_t),
intent(inout) :: this
1724 integer,
intent(in) :: f
1725 integer,
intent(in) :: e
1726 integer,
intent(in) :: pf
1727 integer,
intent(in) :: pe
1728 integer,
intent(inout) :: pids(4)
1730 integer :: i, id, p_local_idx
1733 integer,
dimension(4, 6) :: face_nodes = reshape([&
1741 select type(ele => this%elements(e)%e)
1744 pi => ele%pts(face_nodes(i,f))%p
1745 call pi%set_id(pids(i))
1746 call this%add_point(pi, id)
1747 p_local_idx = this%get_local(this%points(id))
1755 class(
mesh_t),
intent(inout) :: this
1756 type(
point_t),
intent(inout) :: p
1763 if (this%htp%get(tmp, local_id) .gt. 0)
then
1764 call neko_error(
'Invalid global id (local point)')
1772 class(
mesh_t),
intent(inout) :: this
1776 if (this%hte%get(e, local_id) .gt. 0)
then
1777 call neko_error(
'Invalid global id (local edge)')
1784 class(
mesh_t),
intent(inout) :: this
1788 if (this%htf%get(f, local_id) .gt. 0)
then
1789 call neko_error(
'Invalid global id (local facet)')
1796 class(
mesh_t),
intent(inout) :: this
1798 integer :: global_id
1800 global_id = this%get_local(e)
1802 if (this%gdim .eq. 2)
then
1804 global_id = this%ddata%local_to_global_facet(global_id)
1808 global_id = this%ddata%local_to_global_edge(global_id)
1816 class(
mesh_t),
intent(inout) :: this
1818 integer :: global_id
1820 global_id = this%get_local_facet(f)
1823 global_id = this%ddata%local_to_global_facet(global_id)
1833 class(
mesh_t),
intent(inout) :: this
1834 integer,
intent(inout) :: index
1837 if (this%htp%get(index, local_id) .eq. 1)
then
1846 class(
mesh_t),
intent(inout) :: this
1847 type(
point_t),
intent(inout) :: p
1848 integer :: local_index
1851 local_index = this%get_local(p)
1852 shared = this%ddata%shared_point%element(local_index)
1860 class(
mesh_t),
intent(inout) :: this
1862 integer :: local_index
1864 local_index = this%get_local(e)
1865 if (this%gdim .eq. 2)
then
1866 shared = this%ddata%shared_facet%element(local_index)
1868 shared = this%ddata%shared_edge%element(local_index)
1874 class(
mesh_t),
intent(inout) :: this
1876 integer :: local_index
1879 local_index = this%get_local(f)
1880 shared = this%ddata%shared_facet%element(local_index)
1887 class(
mesh_t),
intent(inout) :: this
1889 real(kind=
rp) :: v(8)
1895 if (this%gdim .eq. 3)
then
1898 this%elements(i)%e%pts(2)%p%x, &
1899 this%elements(i)%e%pts(3)%p%x, &
1900 this%elements(i)%e%pts(5)%p%x, &
1901 this%elements(i)%e%pts(1)%p%x &
1905 this%elements(i)%e%pts(4)%p%x, &
1906 this%elements(i)%e%pts(1)%p%x, &
1907 this%elements(i)%e%pts(6)%p%x, &
1908 this%elements(i)%e%pts(2)%p%x &
1912 this%elements(i)%e%pts(1)%p%x, &
1913 this%elements(i)%e%pts(4)%p%x, &
1914 this%elements(i)%e%pts(7)%p%x, &
1915 this%elements(i)%e%pts(3)%p%x &
1919 this%elements(i)%e%pts(3)%p%x, &
1920 this%elements(i)%e%pts(2)%p%x, &
1921 this%elements(i)%e%pts(8)%p%x, &
1922 this%elements(i)%e%pts(4)%p%x &
1926 this%elements(i)%e%pts(6)%p%x, &
1927 this%elements(i)%e%pts(7)%p%x, &
1928 this%elements(i)%e%pts(1)%p%x, &
1929 this%elements(i)%e%pts(5)%p%x &
1933 this%elements(i)%e%pts(8)%p%x, &
1934 this%elements(i)%e%pts(5)%p%x, &
1935 this%elements(i)%e%pts(2)%p%x, &
1936 this%elements(i)%e%pts(6)%p%x &
1940 this%elements(i)%e%pts(5)%p%x, &
1941 this%elements(i)%e%pts(8)%p%x, &
1942 this%elements(i)%e%pts(3)%p%x, &
1943 this%elements(i)%e%pts(7)%p%x &
1947 this%elements(i)%e%pts(7)%p%x, &
1948 this%elements(i)%e%pts(6)%p%x, &
1949 this%elements(i)%e%pts(4)%p%x, &
1950 this%elements(i)%e%pts(8)%p%x &
1953 if (v(1) .le. 0.0_rp .or. &
1954 v(2) .le. 0.0_rp .or. &
1955 v(3) .le. 0.0_rp .or. &
1956 v(4) .le. 0.0_rp .or. &
1957 v(5) .le. 0.0_rp .or. &
1958 v(6) .le. 0.0_rp .or. &
1959 v(7) .le. 0.0_rp .or. &
1960 v(8) .le. 0.0_rp )
then
1962 centroid = this%elements(i)%e%centroid()
1964 write(error_unit,
'(A, A, I0, A, 3G12.5)')
"*** ERROR ***: ", &
1965 "Wrong orientation of mesh element ", i, &
1966 " with centroid ", centroid%x
1974 call neko_error(
"Some mesh elements are not right-handed")
1987 real(kind=
dp),
dimension(3),
intent(in) :: p1, p2, p3, origin
1989 real(kind=
dp) :: vp1(3), vp2(3), vp3(3), cross(3)
1995 cross(1) = vp1(2)*vp2(3) - vp2(3)*vp1(2)
1996 cross(2) = vp1(3)*vp2(1) - vp1(1)*vp2(3)
1997 cross(3) = vp1(1)*vp2(2) - vp1(2)*vp2(1)
1999 v = cross(1)*vp3(1) + cross(2)*vp3(2) + cross(3)*vp3(3)
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.
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_gdim
Geometric dimension.
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
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.
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_gdim
Geometric dimension.
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.
A point in with coordinates .
Integer 2-tuple based stack.
Integer 4-tuple based stack.
Integer*8 based unordered set.