7 use hecmw,
only: kint, kreal
15 real(kind=kreal),
parameter,
private :: nagata_epsilon = 1.0d-4
17 integer(kind=kint),
parameter,
private :: DEBUG = 0
32 real(kind=kreal),
intent(in) :: vertices_in(3,3)
33 real(kind=kreal),
intent(in) :: midpoints_in(3,3)
34 real(kind=kreal),
intent(out) :: nodes_out(3,6)
37 nodes_out(1:3, 1) = vertices_in(1:3, 3)
38 nodes_out(1:3, 2) = vertices_in(1:3, 1)
39 nodes_out(1:3, 3) = vertices_in(1:3, 2)
42 nodes_out(1:3, 4) = midpoints_in(1:3, 3)
43 nodes_out(1:3, 5) = midpoints_in(1:3, 1)
44 nodes_out(1:3, 6) = midpoints_in(1:3, 2)
48 subroutine reorder_normals_tri3n_to_tri6n(normals_in, normals_out)
49 real(kind=kreal),
intent(in) :: normals_in(3,3)
50 real(kind=kreal),
intent(out) :: normals_out(3,3)
53 normals_out(1:3, 1) = normals_in(1:3, 3)
54 normals_out(1:3, 2) = normals_in(1:3, 1)
55 normals_out(1:3, 3) = normals_in(1:3, 2)
56 end subroutine reorder_normals_tri3n_to_tri6n
62 real(kind=kreal),
intent(in) :: currpos(:)
65 integer(kind=kint) :: i, j, nn, gnode, n_node
66 real(kind=kreal) :: normal(3), norm_len
67 real(kind=kreal),
allocatable :: vnormal(:)
70 if (
size(surf) > 0)
then
75 if (
present(hecmesh))
then
76 n_node = hecmesh%n_node
78 if (
size(surf) == 0)
return
79 n_node = maxval([(maxval(surf(i)%nodes), i=1,
size(surf))])
83 allocate(vnormal(3*n_node))
88 nn =
size(surf(i)%nodes)
90 gnode = surf(i)%nodes(j)
91 vnormal(3*(gnode-1)+1:3*(gnode-1)+3) = &
92 vnormal(3*(gnode-1)+1:3*(gnode-1)+3) &
93 + surf(i)%vertex_normals(:, j)
99 if (
present(hecmesh))
then
106 nn =
size(surf(i)%nodes)
108 gnode = surf(i)%nodes(j)
109 normal(:) = vnormal(3*(gnode-1)+1:3*(gnode-1)+3)
110 norm_len = dsqrt(dot_product(normal, normal))
111 if (norm_len > 1.0d-20)
then
112 surf(i)%vertex_normals(:, j) = normal / norm_len
126 real(kind=kreal),
intent(in) :: na_vec(3)
127 real(kind=kreal),
intent(in) :: nb_vec(3)
128 real(kind=kreal),
intent(out) :: cab_a(3,3)
129 real(kind=kreal),
intent(out) :: cab_b(3,3)
131 real(kind=kreal) :: aab(2,3), ata(3,3), ata_orig(3,3), ata_inv(3,3)
132 real(kind=kreal) :: p(3,3)
133 real(kind=kreal) :: epsilon
134 integer(kind=kint) :: i
141 ata = matmul(transpose(aab), aab)
145 epsilon = (ata(1,1)+ata(2,2)+ata(3,3)) * nagata_epsilon
147 ata(i,i) = ata(i,i) + epsilon
155 p = matmul(ata_inv, ata_orig)
160 cab_a(i,i) = cab_a(i,i) + 0.5d0
166 cab_b(i,i) = cab_b(i,i) + 0.5d0
173 real(kind=kreal),
intent(in) :: na_vec(3)
174 real(kind=kreal),
intent(in) :: nb_vec(3)
175 real(kind=kreal),
intent(out) :: cab_a(3,3)
176 real(kind=kreal),
intent(out) :: cab_b(3,3)
178 real(kind=kreal) :: i3(3,3)
179 real(kind=kreal) :: m(3), mnorm
180 real(kind=kreal) :: a1, a2
181 real(kind=kreal) :: beta, den, k
182 real(kind=kreal) :: r(3)
183 real(kind=kreal) :: q(3,3)
184 integer(kind=kint) :: i, j
193 m(:) = na_vec(:) + nb_vec(:)
194 mnorm = sqrt( m(1)*m(1) + m(2)*m(2) + m(3)*m(3) )
196 if (mnorm < 1.0d-12)
then
203 a1 = m(1)*na_vec(1) + m(2)*na_vec(2) + m(3)*na_vec(3)
204 a2 = m(1)*nb_vec(1) + m(2)*nb_vec(2) + m(3)*nb_vec(3)
208 beta = nagata_epsilon
210 den = 16.0d0*(a1*a1 + a2*a2) + beta
213 if (den < 1.0d-20)
then
222 r(:) = a2*nb_vec(:) - a1*na_vec(:)
233 cab_a = 0.5d0*i3 - k*q
234 cab_b = 0.5d0*i3 + k*q
242 integer(kind=kint),
intent(in) :: etype
243 integer(kind=kint),
intent(in) :: nnode
244 real(kind=kreal),
intent(in) :: lpos(2)
245 real(kind=kreal),
intent(in) :: vertex_normals(3,nnode)
246 real(kind=kreal),
intent(out) :: p_matrix(3,nnode*3)
248 real(kind=kreal) :: n(8)
249 real(kind=kreal) :: cab_12_1(3,3), cab_12_2(3,3)
250 real(kind=kreal) :: cab_23_2(3,3), cab_23_3(3,3)
251 real(kind=kreal) :: cab_31_3(3,3), cab_31_1(3,3)
252 real(kind=kreal) :: cab_34_3(3,3), cab_34_4(3,3)
253 real(kind=kreal) :: cab_41_4(3,3), cab_41_1(3,3)
254 real(kind=kreal) :: p1(3,3), p2(3,3), p3(3,3), p4(3,3)
255 real(kind=kreal) :: i3(3,3)
256 real(kind=kreal) :: normals_tri6n(3,3)
257 integer(kind=kint) :: i, j
270 call reorder_normals_tri3n_to_tri6n(vertex_normals, normals_tri6n)
273 call compute_cab(normals_tri6n(:,1), normals_tri6n(:,2), cab_31_3, cab_31_1)
274 call compute_cab(normals_tri6n(:,2), normals_tri6n(:,3), cab_12_1, cab_12_2)
275 call compute_cab(normals_tri6n(:,3), normals_tri6n(:,1), cab_23_2, cab_23_3)
278 p1 = n(1) * i3 + n(4) * cab_31_3 + n(6) * cab_23_3
279 p2 = n(2) * i3 + n(4) * cab_31_1 + n(5) * cab_12_1
280 p3 = n(3) * i3 + n(5) * cab_12_2 + n(6) * cab_23_2
283 p_matrix(1:3, 1:3) = p2
284 p_matrix(1:3, 4:6) = p3
285 p_matrix(1:3, 7:9) = p1
291 call compute_cab(vertex_normals(:,1), vertex_normals(:,2), cab_12_1, cab_12_2)
292 call compute_cab(vertex_normals(:,2), vertex_normals(:,3), cab_23_2, cab_23_3)
293 call compute_cab(vertex_normals(:,3), vertex_normals(:,4), cab_34_3, cab_34_4)
294 call compute_cab(vertex_normals(:,4), vertex_normals(:,1), cab_41_4, cab_41_1)
297 p1 = n(1) * i3 + n(5) * cab_12_1 + n(8) * cab_41_1
298 p2 = n(2) * i3 + n(5) * cab_12_2 + n(6) * cab_23_2
299 p3 = n(3) * i3 + n(6) * cab_23_3 + n(7) * cab_34_3
300 p4 = n(4) * i3 + n(7) * cab_34_4 + n(8) * cab_41_4
303 p_matrix(1:3, 1:3) = p1
304 p_matrix(1:3, 4:6) = p2
305 p_matrix(1:3, 7:9) = p3
306 p_matrix(1:3, 10:12) = p4
309 write(*,*)
"Error: compute_interpolation_matrix_P - Unsupported element type for Nagata patch.",etype
317 real(kind=kreal),
intent(in) :: currpos(:)
318 character(len=HECMW_NAME_LEN),
intent(in) :: contact_name
320 integer(kind=kint) :: i
322 if (
size(surf) == 0)
return
326 call create_intermediate_points_single(surf(i), currpos)
331 call print_surface_elements_to_vtk(surf, currpos, contact_name)
336 subroutine create_intermediate_points_single( surf, currpos )
338 real(kind=kreal),
intent(in) :: currpos(:)
340 integer(kind=kint) :: i, etype
341 real(kind=kreal) :: elem(3,4)
342 real(kind=kreal),
pointer :: vertex_normals(:,:)
343 real(kind=kreal) :: cab_12_1(3,3), cab_12_2(3,3)
344 real(kind=kreal) :: cab_23_2(3,3), cab_23_3(3,3)
345 real(kind=kreal) :: cab_31_3(3,3), cab_31_1(3,3)
346 real(kind=kreal) :: cab_34_3(3,3), cab_34_4(3,3)
347 real(kind=kreal) :: cab_41_4(3,3), cab_41_1(3,3)
350 vertex_normals => surf%vertex_normals
355 if (.not.
associated(surf%intermediate_points))
then
356 allocate(surf%intermediate_points(3,3))
360 elem(1:3,i) = currpos(3*(surf%nodes(i)-1)+1 : 3*surf%nodes(i))
364 call compute_cab(vertex_normals(:,1), vertex_normals(:,2), cab_12_1, cab_12_2)
365 call compute_cab(vertex_normals(:,2), vertex_normals(:,3), cab_23_2, cab_23_3)
366 call compute_cab(vertex_normals(:,3), vertex_normals(:,1), cab_31_3, cab_31_1)
369 surf%intermediate_points(:,1) = matmul(cab_12_1(1:3,1:3), elem(1:3,1)) + matmul(cab_12_2(1:3,1:3), elem(1:3,2))
370 surf%intermediate_points(:,2) = matmul(cab_23_2(1:3,1:3), elem(1:3,2)) + matmul(cab_23_3(1:3,1:3), elem(1:3,3))
371 surf%intermediate_points(:,3) = matmul(cab_31_3(1:3,1:3), elem(1:3,3)) + matmul(cab_31_1(1:3,1:3), elem(1:3,1))
375 if (.not.
associated(surf%intermediate_points))
then
376 allocate(surf%intermediate_points(3,4))
380 elem(1:3,i) = currpos(3*(surf%nodes(i)-1)+1 : 3*surf%nodes(i))
384 call compute_cab(vertex_normals(:,1), vertex_normals(:,2), cab_12_1, cab_12_2)
385 call compute_cab(vertex_normals(:,2), vertex_normals(:,3), cab_23_2, cab_23_3)
386 call compute_cab(vertex_normals(:,3), vertex_normals(:,4), cab_34_3, cab_34_4)
387 call compute_cab(vertex_normals(:,4), vertex_normals(:,1), cab_41_4, cab_41_1)
390 surf%intermediate_points(:,1) = matmul(cab_12_1(1:3,1:3), elem(1:3,1)) + matmul(cab_12_2(1:3,1:3), elem(1:3,2))
391 surf%intermediate_points(:,2) = matmul(cab_23_2(1:3,1:3), elem(1:3,2)) + matmul(cab_23_3(1:3,1:3), elem(1:3,3))
392 surf%intermediate_points(:,3) = matmul(cab_34_3(1:3,1:3), elem(1:3,3)) + matmul(cab_34_4(1:3,1:3), elem(1:3,4))
393 surf%intermediate_points(:,4) = matmul(cab_41_4(1:3,1:3), elem(1:3,4)) + matmul(cab_41_1(1:3,1:3), elem(1:3,1))
396 write(*,*)
"Error: create_intermediate_points - Unsupported element type for Nagata patch.",etype
400 end subroutine create_intermediate_points_single
402 subroutine print_surface_elements_to_vtk( surf, currpos, contact_name )
404 real(kind=kreal),
intent(in) :: currpos(:)
405 character(len=HECMW_NAME_LEN),
intent(in) :: contact_name
407 integer(kind=kint),
parameter :: vtk_unit = 99
408 integer(kind=kint) :: i, j, nn, n_tri, n_quad, n_elem, n_points, n_cells_size, node_id, inode
409 real(kind=kreal) :: coord(3), normal(3)
410 character(len=256) :: filename
418 else if (surf(i)%etype ==
fe_quad4n)
then
423 n_elem = n_tri + n_quad
424 if (n_elem == 0)
return
427 n_points = n_tri * 6 + n_quad * 8
428 n_cells_size = n_tri * 7 + n_quad * 9
431 filename = trim(contact_name) //
'_nagata_debug.vtk'
432 open(unit=vtk_unit, file=filename, status=
'replace', action=
'write', form=
'formatted')
435 write(vtk_unit,
'(A)')
'# vtk DataFile Version 3.0'
436 write(vtk_unit,
'(A,A)')
'Nagata patch debug: ', trim(contact_name)
437 write(vtk_unit,
'(A)')
'ASCII'
438 write(vtk_unit,
'(A)')
'DATASET UNSTRUCTURED_GRID'
442 write(vtk_unit,
'(A,I0,A)')
'POINTS ', n_points,
' float'
445 nn =
size(surf(i)%nodes)
448 inode = surf(i)%nodes(j)
449 coord(1:3) = currpos(3*(inode-1)+1 : 3*inode)
450 write(vtk_unit,
'(3(E15.7,1X))') coord(1), coord(2), coord(3)
454 coord(1:3) = surf(i)%intermediate_points(1:3, j)
455 write(vtk_unit,
'(3(E15.7,1X))') coord(1), coord(2), coord(3)
462 write(vtk_unit,
'(A,I0,1X,I0)')
'CELLS ', n_elem, n_cells_size
466 write(vtk_unit,
'(I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0)') &
467 6, node_id, node_id+1, node_id+2, node_id+3, node_id+4, node_id+5
468 node_id = node_id + 6
469 else if (surf(i)%etype ==
fe_quad4n)
then
470 write(vtk_unit,
'(I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0)') &
471 8, node_id, node_id+1, node_id+2, node_id+3, node_id+4, node_id+5, node_id+6, node_id+7
472 node_id = node_id + 8
478 write(vtk_unit,
'(A,I0)')
'CELL_TYPES ', n_elem
481 write(vtk_unit,
'(I0)') 22
482 else if (surf(i)%etype ==
fe_quad4n)
then
483 write(vtk_unit,
'(I0)') 23
489 write(vtk_unit,
'(A,I0)')
'POINT_DATA ', n_points
490 write(vtk_unit,
'(A)')
'VECTORS vertex_normal float'
493 nn =
size(surf(i)%nodes)
496 normal(1:3) = surf(i)%vertex_normals(1:3, j)
497 write(vtk_unit,
'(3(E15.7,1X))') normal(1), normal(2), normal(3)
501 write(vtk_unit,
'(A)')
'0.0 0.0 0.0'
508 write(*,
'(A,A)')
'VTK debug file written: ', trim(filename)
510 end subroutine print_surface_elements_to_vtk
This module encapsulate the basic functions of all elements provide by this software.
subroutine getshapefunc(fetype, localcoord, func)
Calculate the shape function in natural coordinate system.
integer, parameter fe_tri6n
integer, parameter fe_tri3n
integer, parameter fe_quad4n
integer, parameter fe_quad8n
integer(kind=kint), parameter hecmw_name_len
subroutine hecmw_assemble_r(hecMESH, val, n, m)
subroutine hecmw_update_r(hecMESH, val, n, m)
This module provides aux functions.
subroutine calinverse(NN, A)
calculate inverse of matrix a
This module manages surface elements in 3D It provides basic definition of surface elements (triangla...
subroutine calc_all_surf_vertex_normals(surf, currpos)
Calculate vertex normals for all surface elements (geometric calculation only)
Structure to define surface group.