program main !*****************************************************************************80 ! !! MAIN is the main program for TABLE_TET_MESH. ! ! Discussion: ! ! TABLE_TET_MESH computes a tet mesh of a 3D TABLE dataset. ! ! Usage: ! ! table_tet_mesh input_file_name ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 19 August 2009 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Local, integer ( kind = 4 ), parameter BF_MAX, the maximum number of ! boundary faces. I don't know a reasonable formula for this quantity. ! If it's not large enough, the program will print a warning message. ! ! Local, integer ( kind = 4 ), parameter FC_MAX, the maximum number of faces. ! I don't know a reasonable formula for this quantity. ! If it's not large enough, the program will print a warning message. ! implicit none integer ( kind = 4 ), parameter :: bf_max = 8000 integer ( kind = 4 ), parameter :: fc_max = 40000 integer ( kind = 4 ) arg_num integer ( kind = 4 ), dimension (1:3,1:bf_max) :: bf integer ( kind = 4 ) bf_num integer ( kind = 4 ) dim_num integer ( kind = 4 ) face_num integer ( kind = 4 ), dimension (1:7,1:fc_max) :: fc integer ( kind = 4 ) fc_num integer ( kind = 4 ), allocatable, dimension ( : ) :: ht integer ( kind = 4 ) ht_num integer ( kind = 4 ) i integer ( kind = 4 ) iarg integer ( kind = 4 ) iargc integer ( kind = 4 ) :: ierror = 0 character ( len = 255 ) :: node_filename = ' ' integer ( kind = 4 ) node_num real ( kind = 8 ), allocatable, dimension ( :, : ) :: node_xyz character ( len = 255 ) :: element_filename = ' ' integer ( kind = 4 ) tetra_num integer ( kind = 4 ) tetra_num2 integer ( kind = 4 ), allocatable, dimension ( :, : ) :: tetra_node integer ( kind = 4 ), allocatable, dimension ( : ) :: vm call timestamp ( ) write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'TABLE_TET_MESH' write ( *, '(a)' ) ' FORTRAN90 version' write ( *, '(a)' ) ' Read a real TABLE dataset of N points in 3 dimensions,' write ( *, '(a)' ) ' Compute the Delaunay tet mesh.' write ( *, '(a)' ) ' Write an integer TABLE dataset of the tet mesh.' ! ! Get the number of command line arguments. ! arg_num = iargc ( ) ! ! If at least one command line argument, it's the input file name. ! if ( 1 <= arg_num ) then iarg = 1 call getarg ( iarg, node_filename ) else write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'TABLE_TET_MESH:' write ( *, '(a)' ) ' Please enter the name of the input file.' read ( *, '(a)' ) node_filename end if ! ! Create the output file name from the input file name. ! element_filename = node_filename call file_name_ext_swap ( element_filename, 'tetra.txt' ) ! ! Read the point coordinates. ! call r8mat_header_read ( node_filename, dim_num, node_num ) write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' Read the header of "' // trim ( node_filename ) //'".' write ( *, '(a)' ) ' ' write ( *, '(a,i8)' ) ' Spatial dimension DIM_NUM = ', dim_num write ( *, '(a,i8)' ) ' Number of points NODE_NUM = ', node_num allocate ( node_xyz(1:dim_num,1:node_num) ) call r8mat_data_read ( node_filename, dim_num, node_num, node_xyz ) write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' Read the data in "' // trim ( node_filename ) //'".' call r8mat_transpose_print_some ( dim_num, node_num, node_xyz, 1, 1, 5, 5, & ' 5 by 5 portion of node data read from file:' ) ! ! Determine the tet mesh. ! ht_num = ( 3 * node_num ) / 2 allocate ( ht(ht_num) ) allocate ( vm(1:node_num) ) do i = 1, node_num vm(i) = i end do call dtris3 ( node_num, ht_num, bf_max, fc_max, node_xyz, vm, bf_num, & fc_num, face_num, tetra_num, bf, fc, ht, ierror ) if ( ierror /= 0 ) then write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'TABLE_TET_MESH - Fatal error!' write ( *, '(a,i8)' ) ' DTRIS3 returned IERROR = ', ierror write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'TABLE_TET_MESH' write ( *, '(a)' ) ' ABNORMAL end of execution!' stop end if write ( *, '(a)' ) ' ' write ( *, '(a,i8)' ) ' BF_MAX = ', bf_max write ( *, '(a,i8)' ) ' BF_NUM = ', bf_num write ( *, '(a)' ) ' ' write ( *, '(a,i8)' ) ' FC_MAX = ', fc_max write ( *, '(a,i8)' ) ' FC_NUM = ', fc_num write ( *, '(a)' ) ' ' write ( *, '(a,i8)' ) ' HT_NUM = ', ht_num write ( *, '(a)' ) ' ' write ( *, '(a,i8)' ) ' TETRA_NUM = ', tetra_num allocate ( tetra_node(1:4,1:tetra_num) ) call tetlst ( fc_max, fc_num, vm, fc, tetra_num, tetra_num2, tetra_node ) write ( *, '(a)' ) ' ' write ( *, '(a,i8)' ) ' TETRA_NUM2 = ', tetra_num2 ! ! Print a portion. ! write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' Computed the tet mesh.' call i4mat_transpose_print_some ( 4, tetra_num, tetra_node, 1, 1, & 4, 5, ' 4 by 5 portion of tetra data:' ) ! ! Write the tet mesh to a file. ! call i4mat_write ( element_filename, 4, tetra_num, tetra_node ) write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' Wrote the tetra data to "' & // trim ( element_filename ) //'".' ! ! Free memory. ! deallocate ( ht ) deallocate ( node_xyz ) deallocate ( tetra_node ) deallocate ( vm ) ! ! Terminate. ! write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'TABLE_TET_MESH' write ( *, '(a)' ) ' Normal end of execution.' write ( *, '(a)' ) ' ' call timestamp ( ) stop end subroutine availf ( hdavfc, fc_num, fc_max, fc, ind, ierr ) !*****************************************************************************80 ! !! AVAILF returns the index of the next available record in the FC array. ! ! Discussion: ! ! This routine returns the index of the next available record in the ! FC array, either HDAVFC or FC_NUM+1. ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 07 September 2005 ! ! Author: ! ! Original FORTRAN77 version by Barry Joe. ! FORTRAN90 version by John Burkardt. ! ! Reference: ! ! Barry Joe, ! GEOMPACK - a software package for the generation of meshes ! using geometric algorithms, ! Advances in Engineering Software, ! Volume 13, pages 325-331, 1991. ! ! Parameters: ! ! Input/output, integer ( kind = 4 ) HDAVFC, head pointer of available ! records in FC. ! ! Input/output, integer ( kind = 4 ) FC_NUM, current number of records ! used in FC. ! ! Input, integer ( kind = 4 ) FC_MAX, the maximum number of records ! available in FC. ! ! Input, integer ( kind = 4 ) FC(1:7,1:*), array of face records; see ! routine DTRIS3. ! ! Output, integer ( kind = 4 ) IND, the index of available record (if FC ! not full). ! ! Output, integer ( kind = 4 ) IERR, error flag, which is zero unless an ! error occurred. ! implicit none integer ( kind = 4 ) fc(7,*) integer ( kind = 4 ) fc_num integer ( kind = 4 ) hdavfc integer ( kind = 4 ) ierr integer ( kind = 4 ) ind integer ( kind = 4 ) fc_max ierr = 0 if ( hdavfc /= 0 ) then ind = hdavfc hdavfc = -fc(1,hdavfc) else if ( fc_max <= fc_num ) then ierr = 11 write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'AVAILF - Fatal error!' write ( *, '(a)' ) ' Memory requirements for array FC exceed the' write ( *, '(a,i12)' ) ' current limit of FC_MAX = ', fc_max else fc_num = fc_num + 1 ind = fc_num end if return end subroutine baryth ( a, b, c, d, e, alpha, degen ) !*****************************************************************************80 ! !! BARYTH computes barycentric coordinates of a point in 3D. ! ! Discussion: ! ! This routine computes the barycentric coordinates of a 3D point with ! respect to the four vertices of a tetrahedron. ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 24 January 2009 ! ! Author: ! ! Original FORTRAN77 version by Barry Joe. ! FORTRAN90 version by John Burkardt. ! ! Reference: ! ! Barry Joe, ! GEOMPACK - a software package for the generation of meshes ! using geometric algorithms, ! Advances in Engineering Software, ! Volume 13, pages 325-331, 1991. ! ! Parameters: ! ! Input, real ( kind = 8 ) A(1:3), B(1:3), C(1:3), D(1:3), 4 vertices ! of tetrahedron. ! ! Input, real ( kind = 8 ) E(1:3), fifth point for which ! barycentric coordinates found ! ! Output, real ( kind = 8 ) ALPHA(1:4), the scaled barycentric coordinates ! (if DEGEN = .FALSE.) such that ! E = (ALPHA(1)*A + ALPHA(2)*B + ALPHA(3)*C +ALPHA(4)*D)/DET ! where DET = 6 * (volume of tetra ABCD); an ALPHA(I) may be set to 0 ! after tolerance test to indicate that E is coplanar with a face, so ! sum of ALPHA(I)/DET may not be 1; if the actual barycentric ! coordinates rather than just their signs are needed, ! modify this routine to divide ALPHA(I) by DET. ! ! Output, logical DEGEN, TRUE iff A, B, C, D are coplanar. ! implicit none real ( kind = 8 ) a(3) real ( kind = 8 ) alpha(4) real ( kind = 8 ) amax real ( kind = 8 ) b(3) real ( kind = 8 ) bmax real ( kind = 8 ) c(3) real ( kind = 8 ) cmax real ( kind = 8 ) cp1 real ( kind = 8 ) cp2 real ( kind = 8 ) cp3 real ( kind = 8 ) d(3) real ( kind = 8 ) da(3) real ( kind = 8 ) db(3) real ( kind = 8 ) dc(3) real ( kind = 8 ) de(3) logical degen real ( kind = 8 ) det real ( kind = 8 ) dmax real ( kind = 8 ) e(3) real ( kind = 8 ) ea(3) real ( kind = 8 ) eb(3) real ( kind = 8 ) ec(3) real ( kind = 8 ) emax real ( kind = 8 ) tol tol = 100.0D+00 * epsilon ( tol ) degen = .false. da(1:3) = a(1:3) - d(1:3) db(1:3) = b(1:3) - d(1:3) dc(1:3) = c(1:3) - d(1:3) amax = max ( abs ( a(1) ), abs ( a(2) ), abs ( a(3) ) ) bmax = max ( abs ( b(1) ), abs ( b(2) ), abs ( b(3) ) ) cmax = max ( abs ( c(1) ), abs ( c(2) ), abs ( c(3) ) ) dmax = max ( abs ( d(1) ), abs ( d(2) ), abs ( d(3) ) ) cp1 = db(2) * dc(3) - db(3) * dc(2) cp2 = db(3) * dc(1) - db(1) * dc(3) cp3 = db(1) * dc(2) - db(2) * dc(1) det = da(1) * cp1 + da(2) * cp2 + da(3) * cp3 if ( abs ( det ) <= 0.01D+00 * tol * max ( amax, bmax, cmax, dmax ) ) then degen = .true. return end if de(1:3) = e(1:3) - d(1:3) ea(1:3) = a(1:3) - e(1:3) eb(1:3) = b(1:3) - e(1:3) ec(1:3) = c(1:3) - e(1:3) alpha(1) = de(1) * cp1 + de(2) * cp2 + de(3) * cp3 cp1 = da(2) * de(3) - da(3) * de(2) cp2 = da(3) * de(1) - da(1) * de(3) cp3 = da(1) * de(2) - da(2) * de(1) alpha(2) = dc(1) * cp1 + dc(2) * cp2 + dc(3) * cp3 alpha(3) = db(1) * cp1 + db(2) * cp2 + db(3) * cp3 alpha(4) = ea(1) * ( eb(2) * ec(3) - eb(3) * ec(2) ) & + ea(2) * ( eb(3) * ec(1) - eb(1) * ec(3) ) & + ea(3) * ( eb(1) * ec(2) - eb(2) * ec(1) ) if ( det < 0.0D+00 ) then alpha(1) = -alpha(1) alpha(2) = -alpha(2) alpha(4) = -alpha(4) else alpha(3) = -alpha(3) end if emax = max ( abs ( e(1) ), abs ( e(2) ), abs ( e(3) ) ) if ( abs ( alpha(1) ) <= tol * max ( bmax, cmax, dmax, emax ) ) then alpha(1) = 0.0D+00 end if if ( abs ( alpha(2) ) <= tol * max ( amax, cmax, dmax, emax ) ) then alpha(2) = 0.0D+00 end if if ( abs ( alpha(3) ) <= tol * max ( amax, bmax, dmax, emax ) ) then alpha(3) = 0.0D+00 end if if ( abs ( alpha(4) ) <= tol * max ( amax, bmax, cmax, emax ) ) then alpha(4) = 0.0D+00 end if return end subroutine ccsph ( intest, a, b, c, d, e, center, radsq, in ) !*****************************************************************************80 ! !! CCSPH finds the circumsphere through the vertices of a tetrahedron. ! ! Discussion: ! ! This routine finds the center and the square of the radius of ! the circumsphere through four vertices of a tetrahedron, and ! possibly determines whether a fifth 3D point is inside the sphere. ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 24 January 2009 ! ! Author: ! ! Original FORTRAN77 version by Barry Joe. ! FORTRAN90 version by John Burkardt. ! ! Reference: ! ! Barry Joe, ! GEOMPACK - a software package for the generation of meshes ! using geometric algorithms, ! Advances in Engineering Software, ! Volume 13, pages 325-331, 1991. ! ! Parameters: ! ! Input, logical INTEST, is TRUE, if and only if the test for fifth point ! in sphere is to be made. ! ! Input, real ( kind = 8 ) A(1:3), B(1:3), C(1:3), D(1:3), vertices ! of tetrahedron. ! ! Input, real ( kind = 8 ) E(1:3), a fifth point; referenced if ! and only if INTEST is TRUE. ! ! Output, real ( kind = 8 ) CENTER(1:3), center of sphere; undefined ! if A,B,C,D coplanar. ! ! Output, real ( kind = 8 ) RADSQ, the square of radius of sphere; ! -1 if A,B,C,D coplanar. ! ! Output, integer ( kind = 4 ) IN, contains following value if INTEST ! is .TRUE.: ! 2 if A,B,C,D coplanar; ! 1 if E inside sphere; ! 0 if E on sphere; ! -1 if E outside sphere ! implicit none real ( kind = 8 ) a(3) real ( kind = 8 ) b(3) real ( kind = 8 ) c(3) real ( kind = 8 ) center(3) real ( kind = 8 ) cmax real ( kind = 8 ) cp1 real ( kind = 8 ) cp2 real ( kind = 8 ) cp3 real ( kind = 8 ) d(3) real ( kind = 8 ) da(3) real ( kind = 8 ) db(3) real ( kind = 8 ) dc(3) real ( kind = 8 ) det real ( kind = 8 ) dsq real ( kind = 8 ) e(3) integer ( kind = 4 ) in logical intest real ( kind = 8 ) radsq real ( kind = 8 ) rhs(3) real ( kind = 8 ) tol tol = 100.0D+00 * epsilon ( tol ) da(1:3) = a(1:3) - d(1:3) db(1:3) = b(1:3) - d(1:3) dc(1:3) = c(1:3) - d(1:3) rhs(1) = 0.5D+00 * sum ( da(1:3)**2 ) rhs(2) = 0.5D+00 * sum ( db(1:3)**2 ) rhs(3) = 0.5D+00 * sum ( dc(1:3)**2 ) cmax = max ( & abs ( a(1) ), abs ( a(2) ), abs ( a(3) ), & abs ( b(1) ), abs ( b(2) ), abs ( b(3) ), & abs ( c(1) ), abs ( c(2) ), abs ( c(3) ), & abs ( d(1) ), abs ( d(2) ), abs ( d(3) ) ) cp1 = db(2) * dc(3) - dc(2) * db(3) cp2 = dc(2) * da(3) - da(2) * dc(3) cp3 = da(2) * db(3) - db(2) * da(3) det = da(1) * cp1 + db(1) * cp2 + dc(1) * cp3 if ( abs ( det ) <= 0.01D+00 * tol * cmax ) then radsq = -1.0D+00 in = 2 return end if center(1) = ( rhs(1) * cp1 + rhs(2) * cp2 + rhs(3) * cp3 ) / det cp1 = db(1) * rhs(3) - dc(1) * rhs(2) cp2 = dc(1) * rhs(1) - da(1) * rhs(3) cp3 = da(1) * rhs(2) - db(1) * rhs(1) center(2) = ( da(3) * cp1 + db(3) * cp2 + dc(3) * cp3 ) / det center(3) = -( da(2) * cp1 + db(2) * cp2 + dc(2) * cp3 ) / det radsq = sum ( center(1:3)**2 ) center(1:3) = center(1:3) + d(1:3) if ( intest ) then dsq = sum ( ( e(1:3) - center(1:3) )**2 ) if ( ( 1.0D+00 + tol ) * radsq < dsq ) then in = -1 else if ( dsq < ( 1.0D+00 - tol ) * radsq ) then in = 1 else in = 0 end if end if return end subroutine ch_cap ( c ) !*****************************************************************************80 ! !! CH_CAP capitalizes a single character. ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 19 July 1998 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input/output, character C, the character to capitalize. ! implicit none character c integer ( kind = 4 ) itemp itemp = ichar ( c ) if ( 97 <= itemp .and. itemp <= 122 ) then c = char ( itemp - 32 ) end if return end function ch_eqi ( c1, c2 ) !*****************************************************************************80 ! !! CH_EQI is a case insensitive comparison of two characters for equality. ! ! Example: ! ! CH_EQI ( 'A', 'a' ) is .TRUE. ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 28 July 2000 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, character C1, C2, the characters to compare. ! ! Output, logical CH_EQI, the result of the comparison. ! implicit none logical ch_eqi character c1 character c1_cap character c2 character c2_cap c1_cap = c1 c2_cap = c2 call ch_cap ( c1_cap ) call ch_cap ( c2_cap ) if ( c1_cap == c2_cap ) then ch_eqi = .true. else ch_eqi = .false. end if return end subroutine ch_to_digit ( c, digit ) !*****************************************************************************80 ! !! CH_TO_DIGIT returns the value of a base 10 digit. ! ! Example: ! ! C DIGIT ! --- ----- ! '0' 0 ! '1' 1 ! ... ... ! '9' 9 ! ' ' 0 ! 'X' -1 ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 04 August 1999 ! ! Author: ! ! John Burkardt ! ! Parameters: ! ! Input, character C, the decimal digit, '0' through '9' or blank ! are legal. ! ! Output, integer ( kind = 4 ) DIGIT, the corresponding value. If C was ! 'illegal', then DIGIT is -1. ! implicit none character c integer ( kind = 4 ) digit if ( lge ( c, '0' ) .and. lle ( c, '9' ) ) then digit = ichar ( c ) - 48 else if ( c == ' ' ) then digit = 0 else digit = -1 end if return end subroutine dhpsrt ( k, n, lda, a, map ) !*****************************************************************************80 ! !! DHPSRT sorts a list of double precision points in KD. ! ! Discussion: ! ! This routine uses heapsort to obtain the permutation of N K-dimensional ! double precision points so that the points are in lexicographic ! increasing order. ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 31 August 2005 ! ! Author: ! ! Original FORTRAN77 version by Barry Joe. ! FORTRAN90 version by John Burkardt. ! ! Reference: ! ! Barry Joe, ! GEOMPACK - a software package for the generation of meshes ! using geometric algorithms, ! Advances in Engineering Software, ! Volume 13, pages 325-331, 1991. ! ! Parameters: ! ! Input, integer ( kind = 4 ) K, the dimension of points. ! ! Input, integer ( kind = 4 ) N, the number of points. ! ! Input, integer ( kind = 4 ) LDA, the leading dimension of array A in ! calling routine; K <= LDA. ! ! Input, real ( kind = 8 ) A(1:K,1:*), array of points. ! ! Input/output, integer ( kind = 4 ) MAP(1:N). On input, the points of A ! with indices MAP(1), MAP(2), ..., MAP(N) are to be sorted. On output, ! the elements are permuted so that ! A(*,MAP(1)) <= A(*,MAP(2)) <= ... <= A(*,MAP(N)). ! implicit none integer ( kind = 4 ) lda integer ( kind = 4 ) n real ( kind = 8 ) a(lda,*) integer ( kind = 4 ) i integer ( kind = 4 ) k integer ( kind = 4 ) map(n) integer ( kind = 4 ) t do i = n/2, 1, -1 call dsftdw ( i, n, k, lda, a, map ) end do do i = n, 2, -1 t = map(1) map(1) = map(i) map(i) = t call dsftdw ( 1, i-1, k, lda, a, map ) end do return end function dless ( k, p, q ) !*****************************************************************************80 ! !! DLESS determines the lexicographically lesser of two double precision values. ! ! Discussion: ! ! This routine determines whether P is lexicographically less than Q in ! floating point arithmetic. ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 24 January 2009 ! ! Author: ! ! Original FORTRAN77 version by Barry Joe. ! FORTRAN90 version by John Burkardt. ! ! Reference: ! ! Barry Joe, ! GEOMPACK - a software package for the generation of meshes ! using geometric algorithms, ! Advances in Engineering Software, ! Volume 13, pages 325-331, 1991. ! ! Parameters: ! ! Input, integer ( kind = 4 ) K, dimension of points. ! ! Input, real ( kind = 8 ) P(1:K), Q(1:K), two points. ! ! Output, logical DLESS, TRUE if P < Q, FALSE otherwise. ! implicit none real ( kind = 8 ) cmax logical dless integer ( kind = 4 ) i integer ( kind = 4 ) k real ( kind = 8 ) p(k) real ( kind = 8 ) q(k) real ( kind = 8 ) tol tol = 100.0D+00 * epsilon ( tol ) do i = 1, k cmax = max ( abs ( p(i) ), abs ( q(i) ) ) if ( abs ( p(i) - q(i) ) <= tol * cmax .or. cmax <= tol ) then cycle end if if ( p(i) < q(i) ) then dless = .true. else dless = .false. end if return end do dless = .false. return end subroutine dsftdw ( l, u, k, lda, a, map ) !*****************************************************************************80 ! !! DSFTDW does one step of the heap sort algorithm for double precision data. ! ! Discussion: ! ! This routine sifts A(*,MAP(L)) down a heap of size U. ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 24 January 2009 ! ! Author: ! ! Original FORTRAN77 version by Barry Joe. ! FORTRAN90 version by John Burkardt. ! ! Reference: ! ! Barry Joe, ! GEOMPACK - a software package for the generation of meshes ! using geometric algorithms, ! Advances in Engineering Software, ! Volume 13, pages 325-331, 1991. ! ! Parameters: ! ! Input, integer ( kind = 4 ) L, U, the lower and upper index of ! part of heap. ! ! Input, integer ( kind = 4 ) K, the dimension of points. ! ! Input, integer ( kind = 4 ) LDA, the leading dimension of array A in ! calling routine. ! ! Input, real ( kind = 8 ) A(1:K,1:*), see routine DHPSRT. ! ! Input/output, integer ( kind = 4 ) MAP(1:*), see routine DHPSRT. ! implicit none integer ( kind = 4 ) lda integer ( kind = 4 ) k integer ( kind = 4 ) l integer ( kind = 4 ) map(*) integer ( kind = 4 ) u real ( kind = 8 ) a(lda,*) logical dless integer ( kind = 4 ) i integer ( kind = 4 ) j integer ( kind = 4 ) t i = l j = 2 * i t = map(i) do if ( u < j ) then exit end if if ( j < u ) then if ( dless ( k, a(1,map(j)), a(1,map(j+1)) ) ) then j = j + 1 end if end if if ( dless ( k, a(1,map(j)), a(1,t)) ) then exit end if map(i) = map(j) i = j j = 2 * i end do map(i) = t return end subroutine dtris3 ( npt, sizht, bf_max, fc_max, vcl, vm, bf_num, fc_num, & nface, ntetra, bf, fc, ht, ierr ) !*****************************************************************************80 ! !! DTRIS3 constructs a Delaunay triangulation of vertices in 3D. ! ! Discussion: ! ! This routine constructs a Delaunay triangulation of 3D vertices using ! an incremental approach and local transformations. Vertices are ! first sorted in lexicographically increasing (x,y,z) order, and ! then are inserted one at a time from outside the convex hull. ! ! Licensing: ! ! This code is distributed under the GNU LGPL license. ! ! Modified: ! ! 02 September 2005 ! ! Author: ! ! Original FORTRAN77 version by Barry Joe. ! FORTRAN90 version by John Burkardt. ! ! Reference: ! ! Barry Joe, ! GEOMPACK - a software package for the generation of meshes ! using geometric algorithms, ! Advances in Engineering Software, ! Volume 13, pages 325-331, 1991. ! ! Parameters: ! ! Input, integer ( kind = 4 ) NPT, the number of 3D vertices. ! ! Input, integer ( kind = 4 ) SIZHT, the size of the hash table HT; a good ! choice is a prime number which is about 1/8 * NFACE (or 3/2 * NPT for ! random points from the uniform distribution). ! ! Input, integer ( kind = 4 ) BF_MAX, the maximum size available for BF ! array. This needs to be at least as big as the number of boundary faces. ! ! Input, integer ( kind = 4 ) FC_MAX, the maximum size available for ! FC array. This needs to be at least as big as the number of faces. ! ! Input, real ( kind = 8 ) VCL(1:3,1:NPT), the vertex coordinates. ! In the general case, VCL may contain the coordinates for more ! than NPT vertices, and the VM array is used to select them. ! ! Input/output, integer ( kind = 4 ) VM(1:NPT), the vertices of VCL to be ! triangulated. On output, these indices are permuted, so that ! VCL(*,VM(1)), ... , VCL(*,VM(NPT)) are in lexicographic increasing order, ! with possible slight reordering so first 4 vertices are ! non-coplanar. Typically, the input value of VM might be 1 through ! NPT. ! ! Output, integer ( kind = 4 ) BF_NUM, the number of positions used in BF. ! BF_NUM <= BF_MAX. ! ! Output, integer ( kind = 4 ) FC_NUM, the number of positions used in FC. ! FC_NUM <= FC_MAX. ! ! Output, integer ( kind = 4 ) NFACE, the number of faces in triangulation; ! NFACE <= FC_NUM. ! ! Output, integer ( kind = 4 ) NTETRA, the number of tetrahedra in ! the triangulation. ! ! Output, integer ( kind = 4 ) BF(1:3,1:BF_NUM), boundary face records ! containing pointers (indices) to FC; if FC(5,I) = -J < 0 and ! FC(1:3,I) = ABC, then BF(1,J) points to other boundary face with edge BC, ! BF(2,J) points to other boundary face with edge AC, and ! BF(3,J) points to other boundary face with edge AB; ! if BF(1,J) <= 0, record is not used and is in avail list. ! ! Output, integer ( kind = 4 ) FC(1:7,1:FC_NUM), face records which are in ! linked lists in hash table with direct chaining. Fields are: ! FC(1:3,*) - A,B,C with 1<=A