7 use hecmw,
only: kint, kreal
15 real(kind=kreal),
parameter,
private :: nagata_epsilon = 1.0d-4
17 integer(kind=kint),
parameter,
private :: SMOOTHING_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)
219 call reorder_normals_tri3n_to_tri6n(vertex_normals, normals_tri6n)
222 call compute_cab(normals_tri6n(:,1), normals_tri6n(:,2), cab_31_3, cab_31_1)
223 call compute_cab(normals_tri6n(:,2), normals_tri6n(:,3), cab_12_1, cab_12_2)
224 call compute_cab(normals_tri6n(:,3), normals_tri6n(:,1), cab_23_2, cab_23_3)
227 p1 = n(1) * i3 + n(4) * cab_31_3 + n(6) * cab_23_3
228 p2 = n(2) * i3 + n(4) * cab_31_1 + n(5) * cab_12_1
229 p3 = n(3) * i3 + n(5) * cab_12_2 + n(6) * cab_23_2
232 p_matrix(1:3, 1:3) = p2
233 p_matrix(1:3, 4:6) = p3
234 p_matrix(1:3, 7:9) = p1
240 call compute_cab(vertex_normals(:,1), vertex_normals(:,2), cab_12_1, cab_12_2)
241 call compute_cab(vertex_normals(:,2), vertex_normals(:,3), cab_23_2, cab_23_3)
242 call compute_cab(vertex_normals(:,3), vertex_normals(:,4), cab_34_3, cab_34_4)
243 call compute_cab(vertex_normals(:,4), vertex_normals(:,1), cab_41_4, cab_41_1)
246 p1 = n(1) * i3 + n(5) * cab_12_1 + n(8) * cab_41_1
247 p2 = n(2) * i3 + n(5) * cab_12_2 + n(6) * cab_23_2
248 p3 = n(3) * i3 + n(6) * cab_23_3 + n(7) * cab_34_3
249 p4 = n(4) * i3 + n(7) * cab_34_4 + n(8) * cab_41_4
252 p_matrix(1:3, 1:3) = p1
253 p_matrix(1:3, 4:6) = p2
254 p_matrix(1:3, 7:9) = p3
255 p_matrix(1:3, 10:12) = p4
258 write(*,*)
"Error: compute_interpolation_matrix_P - Unsupported element type for Nagata patch.",etype
266 real(kind=kreal),
intent(in) :: currpos(:)
267 character(len=HECMW_NAME_LEN),
intent(in) :: contact_name
269 integer(kind=kint) :: i
271 if (
size(surf) == 0)
return
275 call create_intermediate_points_single(surf(i), currpos)
279 if( smoothing_debug > 0 )
then
280 call print_surface_elements_to_vtk(surf, currpos, contact_name)
285 subroutine create_intermediate_points_single( surf, currpos )
287 real(kind=kreal),
intent(in) :: currpos(:)
289 integer(kind=kint) :: i, etype
290 real(kind=kreal) :: elem(3,4)
291 real(kind=kreal),
pointer :: vertex_normals(:,:)
292 real(kind=kreal) :: cab_12_1(3,3), cab_12_2(3,3)
293 real(kind=kreal) :: cab_23_2(3,3), cab_23_3(3,3)
294 real(kind=kreal) :: cab_31_3(3,3), cab_31_1(3,3)
295 real(kind=kreal) :: cab_34_3(3,3), cab_34_4(3,3)
296 real(kind=kreal) :: cab_41_4(3,3), cab_41_1(3,3)
299 vertex_normals => surf%vertex_normals
304 if (.not.
associated(surf%intermediate_points))
then
305 allocate(surf%intermediate_points(3,3))
309 elem(1:3,i) = currpos(3*(surf%nodes(i)-1)+1 : 3*surf%nodes(i))
313 call compute_cab(vertex_normals(:,1), vertex_normals(:,2), cab_12_1, cab_12_2)
314 call compute_cab(vertex_normals(:,2), vertex_normals(:,3), cab_23_2, cab_23_3)
315 call compute_cab(vertex_normals(:,3), vertex_normals(:,1), cab_31_3, cab_31_1)
318 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))
319 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))
320 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))
324 if (.not.
associated(surf%intermediate_points))
then
325 allocate(surf%intermediate_points(3,4))
329 elem(1:3,i) = currpos(3*(surf%nodes(i)-1)+1 : 3*surf%nodes(i))
333 call compute_cab(vertex_normals(:,1), vertex_normals(:,2), cab_12_1, cab_12_2)
334 call compute_cab(vertex_normals(:,2), vertex_normals(:,3), cab_23_2, cab_23_3)
335 call compute_cab(vertex_normals(:,3), vertex_normals(:,4), cab_34_3, cab_34_4)
336 call compute_cab(vertex_normals(:,4), vertex_normals(:,1), cab_41_4, cab_41_1)
339 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))
340 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))
341 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))
342 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
351 end subroutine create_intermediate_points_single
353 subroutine print_surface_elements_to_vtk( surf, currpos, contact_name )
355 real(kind=kreal),
intent(in) :: currpos(:)
356 character(len=HECMW_NAME_LEN),
intent(in) :: contact_name
358 integer(kind=kint),
parameter :: vtk_unit = 99
359 integer(kind=kint) :: i, j, nn, n_tri, n_quad, n_elem, n_points, n_cells_size, node_id, inode
360 real(kind=kreal) :: coord(3), normal(3)
361 character(len=256) :: filename
369 else if (surf(i)%etype ==
fe_quad4n)
then
374 n_elem = n_tri + n_quad
375 if (n_elem == 0)
return
378 n_points = n_tri * 6 + n_quad * 8
379 n_cells_size = n_tri * 7 + n_quad * 9
382 filename = trim(contact_name) //
'_nagata_debug.vtk'
383 open(unit=vtk_unit, file=filename, status=
'replace', action=
'write', form=
'formatted')
386 write(vtk_unit,
'(A)')
'# vtk DataFile Version 3.0'
387 write(vtk_unit,
'(A,A)')
'Nagata patch debug: ', trim(contact_name)
388 write(vtk_unit,
'(A)')
'ASCII'
389 write(vtk_unit,
'(A)')
'DATASET UNSTRUCTURED_GRID'
393 write(vtk_unit,
'(A,I0,A)')
'POINTS ', n_points,
' float'
396 nn =
size(surf(i)%nodes)
399 inode = surf(i)%nodes(j)
400 coord(1:3) = currpos(3*(inode-1)+1 : 3*inode)
401 write(vtk_unit,
'(3(E15.7,1X))') coord(1), coord(2), coord(3)
405 coord(1:3) = surf(i)%intermediate_points(1:3, j)
406 write(vtk_unit,
'(3(E15.7,1X))') coord(1), coord(2), coord(3)
413 write(vtk_unit,
'(A,I0,1X,I0)')
'CELLS ', n_elem, n_cells_size
417 write(vtk_unit,
'(I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0)') &
418 6, node_id, node_id+1, node_id+2, node_id+3, node_id+4, node_id+5
419 node_id = node_id + 6
420 else if (surf(i)%etype ==
fe_quad4n)
then
421 write(vtk_unit,
'(I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0,1X,I0)') &
422 8, node_id, node_id+1, node_id+2, node_id+3, node_id+4, node_id+5, node_id+6, node_id+7
423 node_id = node_id + 8
429 write(vtk_unit,
'(A,I0)')
'CELL_TYPES ', n_elem
432 write(vtk_unit,
'(I0)') 22
433 else if (surf(i)%etype ==
fe_quad4n)
then
434 write(vtk_unit,
'(I0)') 23
440 write(vtk_unit,
'(A,I0)')
'POINT_DATA ', n_points
441 write(vtk_unit,
'(A)')
'VECTORS vertex_normal float'
444 nn =
size(surf(i)%nodes)
447 normal(1:3) = surf(i)%vertex_normals(1:3, j)
448 write(vtk_unit,
'(3(E15.7,1X))') normal(1), normal(2), normal(3)
452 write(vtk_unit,
'(A)')
'0.0 0.0 0.0'
459 write(*,
'(A,A)')
'VTK debug file written: ', trim(filename)
461 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.