488 type(
coef_t),
target,
intent(in) :: coef
489 integer :: lx, ly, lz
490 integer :: mid_i, mid_j, mid_k
506 allocate(this%node_rst(3, 8))
507 allocate(this%edge_mid_rst(3, 12))
508 allocate(this%node_linear_idx(8))
509 nface = 2 * coef%msh%gdim
510 allocate(this%face_type(nface, coef%msh%nelv))
511 this%face_type = 5.0_rp
513 this%node_rst(:,1) = [1, 1, 1]
514 this%node_rst(:,2) = [lx, 1, 1]
515 this%node_rst(:,3) = [1, ly, 1]
516 this%node_rst(:,4) = [lx, ly, 1]
517 this%node_rst(:,5) = [1, 1, lz]
518 this%node_rst(:,6) = [lx, 1, lz]
519 this%node_rst(:,7) = [1, ly, lz]
520 this%node_rst(:,8) = [lx, ly, lz]
522 this%edge_mid_rst(:,1) = [mid_i, 1, 1]
523 this%edge_mid_rst(:,2) = [mid_i, ly, 1]
524 this%edge_mid_rst(:,3) = [mid_i, 1, lz]
525 this%edge_mid_rst(:,4) = [mid_i, ly, lz]
526 this%edge_mid_rst(:,5) = [1, mid_j, 1]
527 this%edge_mid_rst(:,6) = [lx, mid_j, 1]
528 this%edge_mid_rst(:,7) = [1, mid_j, lz]
529 this%edge_mid_rst(:,8) = [lx, mid_j, lz]
530 this%edge_mid_rst(:,9) = [1, 1, mid_k]
531 this%edge_mid_rst(:,10) = [lx, 1, mid_k]
532 this%edge_mid_rst(:,11) = [1, ly, mid_k]
533 this%edge_mid_rst(:,12) = [lx, ly, mid_k]
535 this%node_linear_idx(1) =
linear_index(1, 1, 1, 1, lx, ly, lz)
536 this%node_linear_idx(2) =
linear_index(lx, 1, 1, 1, lx, ly, lz)
537 this%node_linear_idx(3) =
linear_index(1, ly, 1, 1, lx, ly, lz)
538 this%node_linear_idx(4) =
linear_index(lx, ly, 1, 1, lx, ly, lz)
539 this%node_linear_idx(5) =
linear_index(1, 1, lz, 1, lx, ly, lz)
540 this%node_linear_idx(6) =
linear_index(lx, 1, lz, 1, lx, ly, lz)
541 this%node_linear_idx(7) =
linear_index(1, ly, lz, 1, lx, ly, lz)
542 this%node_linear_idx(8) =
linear_index(lx, ly, lz, 1, lx, ly, lz)
644 type(
field_t),
pointer :: boundary_mask_field
645 type(
field_t),
pointer :: node_type_field
648 integer,
allocatable :: dirichlet_mask_values(:)
649 integer,
allocatable :: mixed_mask_values(:)
650 integer,
allocatable :: resolved_mask_values(:)
651 integer :: scratch_idx(2)
652 integer :: boundary_size
653 integer :: compact_node_type_idx
654 integer :: boundary_dof_key
655 integer :: i, j, k, dof_size, m
656 integer :: dirichlet_mask_size, mixed_mask_size, resolved_mask_size
658 real(kind=
rp) :: bc_type
659 class(
bc_t),
pointer ::
bc
661 call this%clear_masks()
664 scratch_idx(1), .true.)
666 scratch_idx(2), .true.)
668 dof_size = this%dof%size()
669 this%face_type = 5.0_rp
675 call rzero(boundary_mask_field%x, dof_size)
676 do i = 1, this%bcs%size()
677 bc => this%bcs%get(i)
679 if (.not.
allocated(
bc%msk))
then
680 call neko_error(
"Attempting to finalize coupled projector " // &
690 call cfill_mask(boundary_mask_field%x, 1.0_rp, dof_size, &
691 bc%msk(1:
bc%msk(0)), &
705 call cfill(node_type_field%x, 5.0_rp, dof_size)
707 do i = 1, this%bcs%size()
708 bc => this%bcs%get(i)
714 marked_faces =>
bc%marked_facet%array()
715 do j = 1,
bc%marked_facet%size()
716 marked_face = marked_faces(j)
717 facet = marked_face%x(1)
718 el = marked_face%x(2)
719 this%face_type(facet, el) = bc_type
724 do j = 1,
bc%facet_node_msk(0)
725 m =
bc%facet_node_msk(j)
728 node_type_field%x(m,1,1,1) = min(bc_type, node_type_field%x(m,1,1,1))
738 call this%coef%gs_h%op(node_type_field,
gs_op_min)
749 if (boundary_mask_field%x(i,1,1,1) .gt. 0.5_rp)
then
750 boundary_size = boundary_size + 1
756 allocate(this%boundary_dof(boundary_size))
758 allocate(this%node_type(boundary_size))
760 call this%boundary_idx%init(boundary_size, compact_node_type_idx)
764 if (boundary_mask_field%x(i,1,1,1) .lt. 0.5_rp) cycle
766 boundary_size = boundary_size + 1
767 this%boundary_dof(boundary_size) = i
768 this%node_type(boundary_size) = node_type_field%x(i,1,1,1)
770 compact_node_type_idx = boundary_size
771 call this%boundary_idx%set(boundary_dof_key, compact_node_type_idx)
779 do i = 1, this%bcs%size()
780 bc => this%bcs%get(i)
784 call bc%resolved_msk%free()
792 resolved_mask_size = 0
796 if (abs(node_type_field%x(k,1,1,1) - bc_type) .lt. 1.0e-6_rp)
then
797 resolved_mask_size = resolved_mask_size + 1
801 allocate(resolved_mask_values(resolved_mask_size))
804 resolved_mask_size = 0
807 if (abs(node_type_field%x(k,1,1,1) - bc_type) .lt. 1.0e-6_rp)
then
808 resolved_mask_size = resolved_mask_size + 1
809 resolved_mask_values(resolved_mask_size) = k
813 call bc%resolved_msk%init(resolved_mask_values, resolved_mask_size)
814 deallocate(resolved_mask_values)
820 dirichlet_mask_size = 0
826 if (boundary_mask_field%x(i,1,1,1) .lt. 0.5_rp) cycle
828 if (node_type_field%x(i,1,1,1) .lt. 1.9_rp)
then
829 dirichlet_mask_size = dirichlet_mask_size + 1
830 else if (node_type_field%x(i,1,1,1) .gt. 1.9_rp .and. &
831 node_type_field%x(i,1,1,1) .lt. 3.9_rp)
then
832 mixed_mask_size = mixed_mask_size + 1
837 allocate(dirichlet_mask_values(dirichlet_mask_size))
838 allocate(mixed_mask_values(mixed_mask_size))
842 dirichlet_mask_size = 0
845 if (boundary_mask_field%x(i,1,1,1) .lt. 0.5_rp) cycle
847 if (node_type_field%x(i,1,1,1) .lt. 1.9_rp)
then
848 dirichlet_mask_size = dirichlet_mask_size + 1
849 dirichlet_mask_values(dirichlet_mask_size) = i
850 else if (node_type_field%x(i,1,1,1) .gt. 1.9_rp .and. &
851 node_type_field%x(i,1,1,1) .lt. 3.9_rp)
then
852 mixed_mask_size = mixed_mask_size + 1
853 mixed_mask_values(mixed_mask_size) = i
859 call this%dirichlet_dof_mask%init(dirichlet_mask_values, &
861 call this%mixed_dof_mask%init(mixed_mask_values, mixed_mask_size)
864 allocate(this%constraint_n(mixed_mask_size))
865 allocate(this%constraint_t1(mixed_mask_size))
866 allocate(this%constraint_t2(mixed_mask_size))
868 call device_map(this%constraint_n, this%constraint_n_d, &
869 size(this%constraint_n))
870 call device_map(this%constraint_t1, this%constraint_t1_d, &
871 size(this%constraint_t1))
872 call device_map(this%constraint_t2, this%constraint_t2_d, &
873 size(this%constraint_t2))
881 do i = 1, mixed_mask_size
882 j = mixed_mask_values(i)
884 if (node_type_field%x(j,1,1,1) .lt. 1.9_rp)
then
885 this%constraint_n(i) = 1
886 this%constraint_t1(i) = 1
887 this%constraint_t2(i) = 1
888 else if (node_type_field%x(j,1,1,1) .gt. 1.9_rp .and. &
889 node_type_field%x(j,1,1,1) .lt. 2.9_rp)
then
890 this%constraint_n(i) = 1
891 this%constraint_t1(i) = 0
892 this%constraint_t2(i) = 0
893 else if (node_type_field%x(j,1,1,1) .gt. 2.9_rp .and. &
894 node_type_field%x(j,1,1,1) .lt. 3.9_rp)
then
895 this%constraint_n(i) = 0
896 this%constraint_t1(i) = 1
897 this%constraint_t2(i) = 1
898 else if (node_type_field%x(j,1,1,1) .gt. 3.9_rp)
then
899 this%constraint_n(i) = 0
900 this%constraint_t1(i) = 0
901 this%constraint_t2(i) = 0
906 deallocate(dirichlet_mask_values)
907 deallocate(mixed_mask_values)
919 type(
field_t),
pointer :: normal_x_field
920 type(
field_t),
pointer :: normal_y_field
921 type(
field_t),
pointer :: normal_z_field
922 class(
bc_t),
pointer :: bc
923 integer,
pointer :: mixed_dof_values(:)
924 integer,
allocatable :: dof_to_mixed_idx(:)
925 integer :: scratch_idx(3)
926 integer :: node_type_lookup_status, compact_node_type_idx
927 integer :: i, j, k, dof_size, m
928 integer :: idx(4), facet, el, edge, node, ii, p
929 integer :: rst(3), rst1(3), rst2(3), step_rst(3)
930 integer :: edge_len, edge_idx, node_idx
931 real(kind=
rp) :: normal(3), t1_vec(3), t2_vec(3), len, bc_type
932 real(kind=
rp),
parameter :: normal_tol = 100.0_rp * epsilon(1.0_rp)
933 character(len=LOG_SIZE) :: error_msg
935 call this%clear_basis()
944 dof_size = this%dof%size()
945 m = this%mixed_dof_mask%size()
946 mixed_dof_values => this%mixed_dof_mask%get()
948 call this%n%init(3, m)
949 call this%t1%init(3, m)
950 call this%t2%init(3, m)
954 allocate(dof_to_mixed_idx(dof_size))
963 dof_to_mixed_idx(mixed_dof_values(i)) = i
979 call rzero(normal_x_field%x, dof_size)
980 call rzero(normal_y_field%x, dof_size)
981 call rzero(normal_z_field%x, dof_size)
987 do i = 1, this%bcs%size()
988 bc => this%bcs%get(i)
995 do j = 1,
bc%facet_node_msk(0)
997 k =
bc%facet_node_msk(j)
1004 if (this%face_type(facet, idx(4)) .lt. 1.9_rp .or. &
1005 this%face_type(facet, idx(4)) .gt. 3.1_rp) cycle
1007 normal = this%coef%get_normal(idx(1), idx(2), idx(3), idx(4), &
1009 normal_x_field%x(k,1,1,1) = normal(1)
1010 normal_y_field%x(k,1,1,1) = normal(2)
1011 normal_z_field%x(k,1,1,1) = normal(3)
1052 do el = 1, this%coef%msh%nelv
1055 rst = this%edge_mid_rst(:, edge)
1059 this%coef%Xh%lx, this%coef%Xh%ly, this%coef%Xh%lz)
1062 node_type_lookup_status = this%boundary_idx%get( &
1063 edge_idx, compact_node_type_idx)
1067 if (node_type_lookup_status .ne. 0) cycle
1068 bc_type = abs(this%node_type(compact_node_type_idx))
1071 if (bc_type .lt. 1.9_rp .or. bc_type .gt. 3.1_rp) cycle
1083 edge_len = maxval(abs(rst2 - rst1)) + 1
1089 if (rst2(ii) .gt. rst1(ii))
then
1091 else if (rst2(ii) .lt. rst1(ii))
then
1097 do p = 2, edge_len - 1
1098 rst = rst1 + (p - 1) * step_rst
1100 this%coef%Xh%lx, this%coef%Xh%ly, this%coef%Xh%lz)
1101 normal_x_field%x(k,1,1,1) = 0.0_rp
1102 normal_y_field%x(k,1,1,1) = 0.0_rp
1103 normal_z_field%x(k,1,1,1) = 0.0_rp
1112 if (abs(bc_type - this%face_type(facet, el)) .gt. 1.0e-6_rp)
then
1117 do p = 2, edge_len - 1
1118 rst = rst1 + (p - 1) * step_rst
1120 this%coef%Xh%lx, this%coef%Xh%ly, this%coef%Xh%lz)
1121 normal = this%coef%get_normal(rst(1), rst(2), rst(3), &
1123 normal_x_field%x(k,1,1,1) = &
1124 normal_x_field%x(k,1,1,1) + normal(1)
1125 normal_y_field%x(k,1,1,1) = &
1126 normal_y_field%x(k,1,1,1) + normal(2)
1127 normal_z_field%x(k,1,1,1) = &
1128 normal_z_field%x(k,1,1,1) + normal(3)
1139 do el = 1, this%coef%msh%nelv
1140 do node = 1,
size(this%node_linear_idx)
1141 rst = this%node_rst(:, node)
1143 this%coef%Xh%lx, this%coef%Xh%ly, this%coef%Xh%lz)
1145 node_type_lookup_status = this%boundary_idx%get( &
1146 node_idx, compact_node_type_idx)
1147 if (node_type_lookup_status .ne. 0) cycle
1148 bc_type = abs(this%node_type(compact_node_type_idx))
1151 if (bc_type .lt. 1.9_rp .or. bc_type .gt. 3.1_rp) cycle
1154 normal_x_field%x(node_idx,1,1,1) = 0.0_rp
1155 normal_y_field%x(node_idx,1,1,1) = 0.0_rp
1156 normal_z_field%x(node_idx,1,1,1) = 0.0_rp
1159 do ii = 1, this%coef%msh%gdim
1163 if (abs(bc_type - this%face_type(facet, el)) .gt. 1.0e-6_rp)
then
1168 normal = this%coef%get_normal(rst(1), rst(2), rst(3), &
1170 normal_x_field%x(node_idx,1,1,1) = &
1171 normal_x_field%x(node_idx,1,1,1) + normal(1)
1172 normal_y_field%x(node_idx,1,1,1) = &
1173 normal_y_field%x(node_idx,1,1,1) + normal(2)
1174 normal_z_field%x(node_idx,1,1,1) = &
1175 normal_z_field%x(node_idx,1,1,1) + normal(3)
1202 if (this%coef%cyclic)
then
1203 call rotate_cyc(normal_x_field%x, normal_y_field%x, normal_z_field%x, &
1207 call this%coef%gs_h%op(normal_x_field,
gs_op_add)
1208 call this%coef%gs_h%op(normal_y_field,
gs_op_add)
1209 call this%coef%gs_h%op(normal_z_field,
gs_op_add)
1211 if (this%coef%cyclic)
then
1212 call rotate_cyc(normal_x_field%x, normal_y_field%x, normal_z_field%x, &
1231 j = mixed_dof_values(i)
1234 normal(1) = normal_x_field%x(j,1,1,1)
1235 normal(2) = normal_y_field%x(j,1,1,1)
1236 normal(3) = normal_z_field%x(j,1,1,1)
1237 len = sqrt(sum(normal**2))
1238 if (len .le. normal_tol)
then
1239 write(error_msg,
'(A,I0,A,ES13.6,A)') &
1240 "Coupled vector BC projector could not construct a normal " // &
1241 "at local DOF ", j,
" (norm = ", len,
")."
1245 this%n%x(:,i) = normal / len
1250 if (abs(this%n%x(3,i)) .gt. 0.999_rp)
then
1251 t1_vec = [ this%n%x(3,i), 0.0_rp, -this%n%x(1,i) ]
1253 t1_vec = [ -this%n%x(2,i), this%n%x(1,i), 0.0_rp ]
1255 len = sqrt(sum(t1_vec**2))
1256 if (len .gt. 0.0_rp)
then
1257 this%t1%x(:,i) = t1_vec / len
1261 t2_vec(1) = this%n%x(2,i) * this%t1%x(3,i) - &
1262 this%n%x(3,i) * this%t1%x(2,i)
1263 t2_vec(2) = this%n%x(3,i) * this%t1%x(1,i) - &
1264 this%n%x(1,i) * this%t1%x(3,i)
1265 t2_vec(3) = this%n%x(1,i) * this%t1%x(2,i) - &
1266 this%n%x(2,i) * this%t1%x(1,i)
1267 len = sqrt(sum(t2_vec**2))
1268 if (len .gt. 0.0_rp)
then
1269 this%t2%x(:,i) = t2_vec / len
1275 call device_memcpy(this%constraint_n, this%constraint_n_d, &
1277 call device_memcpy(this%constraint_t1, this%constraint_t1_d, &
1279 call device_memcpy(this%constraint_t2, this%constraint_t2_d, &
1289 do i = 1, this%bcs%size()
1290 bc => this%bcs%get(i)
1294 m =
bc%resolved_msk%size()
1295 call bc%n%init(3, m)
1296 call bc%t1%init(3, m)
1297 call bc%t2%init(3, m)
1300 k =
bc%resolved_msk%get(j)
1301 p = dof_to_mixed_idx(k)
1304 call neko_error(
"Mixed BC resolved_msk entry missing from " // &
1305 "the coupled projector mixed basis.")
1308 bc%n%x(:,j) = this%n%x(:,p)
1309 bc%t1%x(:,j) = this%t1%x(:,p)
1310 bc%t2%x(:,j) = this%t2%x(:,p)
1321 if (
allocated(dof_to_mixed_idx))
deallocate(dof_to_mixed_idx)
1425 character(len=*),
intent(in),
optional :: field_name
1426 type(
field_t),
pointer :: mask_field
1427 type(
field_t),
pointer :: nx_field, ny_field, nz_field
1430 integer :: scratch_idx(4)
1431 integer,
pointer :: mixed_mask_values(:)
1432 integer :: dof_size, mixed_mask_size
1433 character(len=:),
allocatable :: field_name_
1435 if (
present(field_name))
then
1436 field_name_ = trim(field_name)
1438 field_name_ =
'bc_projector'
1446 dof_size = this%dof%size()
1447 mixed_mask_size = this%mixed_dof_mask%size()
1449 call rzero(mask_field%x, dof_size)
1450 call rzero(nx_field%x, dof_size)
1451 call rzero(ny_field%x, dof_size)
1452 call rzero(nz_field%x, dof_size)
1454 if (this%mixed_dof_mask%is_set())
then
1455 mixed_mask_values => this%mixed_dof_mask%get()
1457 mixed_mask_values, dof_size, mixed_mask_size)
1459 mixed_mask_values, dof_size, mixed_mask_size)
1461 mixed_mask_values, dof_size, mixed_mask_size)
1467 if (this%dirichlet_dof_mask%is_set())
then
1469 this%dirichlet_dof_mask%get_d(), &
1470 this%dirichlet_dof_mask%size())
1473 if (this%mixed_dof_mask%is_set())
then
1475 this%mixed_dof_mask%get_d(), this%mixed_dof_mask%size())
1478 call device_memcpy(mask_field%x, mask_field%x_d, dof_size, &
1482 call cfill(mask_field%x, 5.0_rp, dof_size)
1484 if (this%dirichlet_dof_mask%is_set())
then
1485 call cfill_mask(mask_field%x, 1.0_rp, dof_size, &
1486 this%dirichlet_dof_mask%get(), this%dirichlet_dof_mask%size())
1489 if (this%mixed_dof_mask%is_set())
then
1490 call cfill_mask(mask_field%x, 2.0_rp, dof_size, &
1491 this%mixed_dof_mask%get(), this%mixed_dof_mask%size())
1495 call basis_fields%init(4)
1496 call basis_fields%assign(1, mask_field)
1497 call basis_fields%assign(2, nx_field)
1498 call basis_fields%assign(3, ny_field)
1499 call basis_fields%assign(4, nz_field)
1501 call basis_file%init(field_name_ //
'.fld')
1502 call basis_file%write(basis_fields)
1503 call basis_fields%free()
1519 this, x, y, z, n, field_name)
1521 integer,
intent(in) :: n
1522 real(kind=
rp),
intent(in) :: x(n)
1523 real(kind=
rp),
intent(in) :: y(n)
1524 real(kind=
rp),
intent(in) :: z(n)
1525 character(len=*),
intent(in),
optional :: field_name
1526 type(
field_t),
pointer :: normal_component_field
1527 type(
field_t),
pointer :: normal_component_coef_field
1530 type(
field_t),
pointer :: projector_nx_field, projector_ny_field, projector_nz_field
1531 type(
field_t),
pointer :: coef_nx_field, coef_ny_field, coef_nz_field
1534 integer :: scratch_idx(8)
1535 integer,
pointer :: mixed_mask_values(:)
1536 integer,
allocatable :: mixed_lut(:)
1537 integer :: dof_size, mixed_mask_size
1538 integer :: i, j, m, k, facet
1540 real(kind=
rp) :: coef_normal(3)
1541 class(
bc_t),
pointer ::
bc
1542 character(len=:),
allocatable :: field_name_
1544 if (
present(field_name))
then
1545 field_name_ = trim(field_name)
1547 field_name_ =
'bc_projector_normal_component'
1551 scratch_idx(1), .true.)
1553 scratch_idx(2), .true.)
1555 scratch_idx(3), .true.)
1557 scratch_idx(4), .true.)
1559 scratch_idx(5), .true.)
1561 scratch_idx(6), .true.)
1563 scratch_idx(7), .true.)
1565 scratch_idx(8), .true.)
1567 dof_size = this%dof%size()
1568 mixed_mask_size = this%mixed_dof_mask%size()
1569 call rzero(normal_component_field%x, dof_size)
1570 call rzero(normal_component_coef_field%x, dof_size)
1571 call rzero(projector_nx_field%x, dof_size)
1572 call rzero(projector_ny_field%x, dof_size)
1573 call rzero(projector_nz_field%x, dof_size)
1574 call rzero(coef_nx_field%x, dof_size)
1575 call rzero(coef_ny_field%x, dof_size)
1576 call rzero(coef_nz_field%x, dof_size)
1578 allocate(mixed_lut(dof_size))
1580 if (this%mixed_dof_mask%is_set())
then
1581 mixed_mask_values => this%mixed_dof_mask%get()
1582 do i = 1, mixed_mask_size
1583 mixed_lut(mixed_mask_values(i)) = i
1587 do i = 1, this%bcs%size()
1588 bc => this%bcs%get(i)
1589 do m = 1,
bc%facet_node_msk(0)
1590 k =
bc%facet_node_msk(m)
1595 coef_normal = this%coef%get_normal(idx(1), idx(2), idx(3), idx(4), &
1597 coef_nx_field%x(k,1,1,1) = coef_normal(1)
1598 coef_ny_field%x(k,1,1,1) = coef_normal(2)
1599 coef_nz_field%x(k,1,1,1) = coef_normal(3)
1600 normal_component_coef_field%x(k,1,1,1) = &
1601 x(k) * coef_normal(1) + y(k) * coef_normal(2) + z(k) * coef_normal(3)
1605 projector_nx_field%x(k,1,1,1) = this%n%x(1,j)
1606 projector_ny_field%x(k,1,1,1) = this%n%x(2,j)
1607 projector_nz_field%x(k,1,1,1) = this%n%x(3,j)
1608 normal_component_field%x(k,1,1,1) = &
1609 x(k) * this%n%x(1,j) + y(k) * this%n%x(2,j) + z(k) * this%n%x(3,j)
1614 deallocate(mixed_lut)
1616 call output_fields%init(2)
1617 call output_fields%assign(1, normal_component_field)
1618 call output_fields%assign(2, normal_component_coef_field)
1619 call output_file%init(field_name_ //
'.fld')
1620 call output_file%write(output_fields)
1621 call output_fields%free()
1623 call normals_fields%init(3)
1624 call normals_fields%assign(1, projector_nx_field)
1625 call normals_fields%assign(2, projector_ny_field)
1626 call normals_fields%assign(3, projector_nz_field)
1627 call normals_file%init(field_name_ //
'_projector_normals.fld')
1628 call normals_file%write(normals_fields)
1629 call normals_fields%free()
1631 call normals_fields%init(3)
1632 call normals_fields%assign(1, coef_nx_field)
1633 call normals_fields%assign(2, coef_ny_field)
1634 call normals_fields%assign(3, coef_nz_field)
1635 call normals_file%init(field_name_ //
'_coef_normals.fld')
1636 call normals_file%write(normals_fields)
1637 call normals_fields%free()