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
123 real(kind=kreal),
intent(in) :: na_vec(3)
124 real(kind=kreal),
intent(in) :: nb_vec(3)
125 real(kind=kreal),
intent(out) :: cab_a(3,3)
126 real(kind=kreal),
intent(out) :: cab_b(3,3)
128 real(kind=kreal) :: i3(3,3)
129 real(kind=kreal) :: m(3), mnorm
130 real(kind=kreal) :: a1, a2
131 real(kind=kreal) :: beta, den, k
132 real(kind=kreal) :: r(3)
133 real(kind=kreal) :: q(3,3)
134 integer(kind=kint) :: i, j
143 m(:) = na_vec(:) + nb_vec(:)
144 mnorm = sqrt( m(1)*m(1) + m(2)*m(2) + m(3)*m(3) )
146 if (mnorm < 1.0d-12)
then
153 a1 = m(1)*na_vec(1) + m(2)*na_vec(2) + m(3)*na_vec(3)
154 a2 = m(1)*nb_vec(1) + m(2)*nb_vec(2) + m(3)*nb_vec(3)
158 beta = nagata_epsilon
160 den = 16.0d0*(a1*a1 + a2*a2) + beta
163 if (den < 1.0d-20)
then
172 r(:) = a2*nb_vec(:) - a1*na_vec(:)
183 cab_a = 0.5d0*i3 - k*q
184 cab_b = 0.5d0*i3 + k*q
192 integer(kind=kint),
intent(in) :: etype
193 integer(kind=kint),
intent(in) :: nnode
194 real(kind=kreal),
intent(in) :: lpos(2)
195 real(kind=kreal),
intent(in) :: vertex_normals(3,nnode)
196 real(kind=kreal),
intent(out) :: p_matrix(3,nnode*3)
198 real(kind=kreal) :: n(8)
199 real(kind=kreal) :: cab_12_1(3,3), cab_12_2(3,3)
200 real(kind=kreal) :: cab_23_2(3,3), cab_23_3(3,3)
201 real(kind=kreal) :: cab_31_3(3,3), cab_31_1(3,3)
202 real(kind=kreal) :: cab_34_3(3,3), cab_34_4(3,3)
203 real(kind=kreal) :: cab_41_4(3,3), cab_41_1(3,3)
204 real(kind=kreal) :: p1(3,3), p2(3,3), p3(3,3), p4(3,3)
205 real(kind=kreal) :: i3(3,3)
206 real(kind=kreal) :: normals_tri6n(3,3)
207 integer(kind=kint) :: i, j
220 call reorder_normals_tri3n_to_tri6n(vertex_normals, normals_tri6n)
223 call compute_cab(normals_tri6n(:,1), normals_tri6n(:,2), cab_31_3, cab_31_1)
224 call compute_cab(normals_tri6n(:,2), normals_tri6n(:,3), cab_12_1, cab_12_2)
225 call compute_cab(normals_tri6n(:,3), normals_tri6n(:,1), cab_23_2, cab_23_3)
228 p1 = n(1) * i3 + n(4) * cab_31_3 + n(6) * cab_23_3
229 p2 = n(2) * i3 + n(4) * cab_31_1 + n(5) * cab_12_1
230 p3 = n(3) * i3 + n(5) * cab_12_2 + n(6) * cab_23_2
233 p_matrix(1:3, 1:3) = p2
234 p_matrix(1:3, 4:6) = p3
235 p_matrix(1:3, 7:9) = p1
241 call compute_cab(vertex_normals(:,1), vertex_normals(:,2), cab_12_1, cab_12_2)
242 call compute_cab(vertex_normals(:,2), vertex_normals(:,3), cab_23_2, cab_23_3)
243 call compute_cab(vertex_normals(:,3), vertex_normals(:,4), cab_34_3, cab_34_4)
244 call compute_cab(vertex_normals(:,4), vertex_normals(:,1), cab_41_4, cab_41_1)
247 p1 = n(1) * i3 + n(5) * cab_12_1 + n(8) * cab_41_1
248 p2 = n(2) * i3 + n(5) * cab_12_2 + n(6) * cab_23_2
249 p3 = n(3) * i3 + n(6) * cab_23_3 + n(7) * cab_34_3
250 p4 = n(4) * i3 + n(7) * cab_34_4 + n(8) * cab_41_4
253 p_matrix(1:3, 1:3) = p1
254 p_matrix(1:3, 4:6) = p2
255 p_matrix(1:3, 7:9) = p3
256 p_matrix(1:3, 10:12) = p4
259 write(*,*)
"Error: compute_interpolation_matrix_P - Unsupported element type for Nagata patch.",etype
267 real(kind=kreal),
intent(in) :: currpos(:)
268 character(len=HECMW_NAME_LEN),
intent(in) :: contact_name
270 integer(kind=kint) :: i
272 if (
size(surf) == 0)
return
276 call create_intermediate_points_single(surf(i), currpos)
281 call print_surface_elements_to_vtk(surf, currpos, contact_name)
286 subroutine create_intermediate_points_single( surf, currpos )
288 real(kind=kreal),
intent(in) :: currpos(:)
290 integer(kind=kint) :: i, etype
291 real(kind=kreal) :: elem(3,4)
292 real(kind=kreal),
pointer :: vertex_normals(:,:)
293 real(kind=kreal) :: cab_12_1(3,3), cab_12_2(3,3)
294 real(kind=kreal) :: cab_23_2(3,3), cab_23_3(3,3)
295 real(kind=kreal) :: cab_31_3(3,3), cab_31_1(3,3)
296 real(kind=kreal) :: cab_34_3(3,3), cab_34_4(3,3)
297 real(kind=kreal) :: cab_41_4(3,3), cab_41_1(3,3)
300 vertex_normals => surf%vertex_normals
305 if (.not.
associated(surf%intermediate_points))
then
306 allocate(surf%intermediate_points(3,3))
310 elem(1:3,i) = currpos(3*(surf%nodes(i)-1)+1 : 3*surf%nodes(i))
314 call compute_cab(vertex_normals(:,1), vertex_normals(:,2), cab_12_1, cab_12_2)
315 call compute_cab(vertex_normals(:,2), vertex_normals(:,3), cab_23_2, cab_23_3)
316 call compute_cab(vertex_normals(:,3), vertex_normals(:,1), cab_31_3, cab_31_1)
319 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))
320 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))
321 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))
325 if (.not.
associated(surf%intermediate_points))
then
326 allocate(surf%intermediate_points(3,4))
330 elem(1:3,i) = currpos(3*(surf%nodes(i)-1)+1 : 3*surf%nodes(i))
334 call compute_cab(vertex_normals(:,1), vertex_normals(:,2), cab_12_1, cab_12_2)
335 call compute_cab(vertex_normals(:,2), vertex_normals(:,3), cab_23_2, cab_23_3)
336 call compute_cab(vertex_normals(:,3), vertex_normals(:,4), cab_34_3, cab_34_4)
337 call compute_cab(vertex_normals(:,4), vertex_normals(:,1), cab_41_4, cab_41_1)
340 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))
341 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))
342 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))
343 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))
346 write(*,*)
"Error: create_intermediate_points - Unsupported element type for Nagata patch.",etype
350 end subroutine create_intermediate_points_single
352 subroutine print_surface_elements_to_vtk( surf, currpos, contact_name )
354 real(kind=kreal),
intent(in) :: currpos(:)
355 character(len=HECMW_NAME_LEN),
intent(in) :: contact_name
357 integer(kind=kint),
parameter :: vtk_unit = 99
358 integer(kind=kint) :: i, j, nn, n_tri, n_quad, n_elem, n_points, n_cells_size, node_id, inode
359 real(kind=kreal) :: coord(3), normal(3)
360 character(len=256) :: filename
368 else if (surf(i)%etype ==
fe_quad4n)
then
373 n_elem = n_tri + n_quad
374 if (n_elem == 0)
return
377 n_points = n_tri * 6 + n_quad * 8
378 n_cells_size = n_tri * 7 + n_quad * 9
381 filename = trim(contact_name) //
'_nagata_debug.vtk'
382 open(unit=vtk_unit, file=filename, status=
'replace', action=
'write', form=
'formatted')
385 write(vtk_unit,
'(A)')
'# vtk DataFile Version 3.0'
386 write(vtk_unit,
'(A,A)')
'Nagata patch debug: ', trim(contact_name)
387 write(vtk_unit,
'(A)')
'ASCII'
388 write(vtk_unit,
'(A)')
'DATASET UNSTRUCTURED_GRID'
392 write(vtk_unit,
'(A,I0,A)')
'POINTS ', n_points,
' float'
395 nn =
size(surf(i)%nodes)
398 inode = surf(i)%nodes(j)
399 coord(1:3) = currpos(3*(inode-1)+1 : 3*inode)
400 write(vtk_unit,
'(3(E15.7,1X))') coord(1), coord(2), coord(3)
404 coord(1:3) = surf(i)%intermediate_points(1:3, j)
405 write(vtk_unit,
'(3(E15.7,1X))') coord(1), coord(2), coord(3)
412 write(vtk_unit,
'(A,I0,1X,I0)')
'CELLS ', n_elem, n_cells_size
416 write(vtk_unit,
'(I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0)') &
417 6, node_id, node_id+1, node_id+2, node_id+3, node_id+4, node_id+5
418 node_id = node_id + 6
419 else if (surf(i)%etype ==
fe_quad4n)
then
420 write(vtk_unit,
'(I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0)') &
421 8, node_id, node_id+1, node_id+2, node_id+3, node_id+4, node_id+5, node_id+6, node_id+7
422 node_id = node_id + 8
428 write(vtk_unit,
'(A,I0)')
'CELL_TYPES ', n_elem
431 write(vtk_unit,
'(I0)') 22
432 else if (surf(i)%etype ==
fe_quad4n)
then
433 write(vtk_unit,
'(I0)') 23
439 write(vtk_unit,
'(A,I0)')
'POINT_DATA ', n_points
440 write(vtk_unit,
'(A)')
'VECTORS vertex_normal float'
443 nn =
size(surf(i)%nodes)
446 normal(1:3) = surf(i)%vertex_normals(1:3, j)
447 write(vtk_unit,
'(3(E15.7,1X))') normal(1), normal(2), normal(3)
451 write(vtk_unit,
'(A)')
'0.0 0.0 0.0'
458 write(*,
'(A,A)')
'VTK debug file written: ', trim(filename)
460 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.