14 nullify (string%nodeData, &
31 string%XzipNodeUsed, &
43 integer(kind=intType) :: i
45 if (
associated(string%nodeData)) &
46 deallocate (string%nodeData)
48 if (
associated(string%intNodeData)) &
49 deallocate (string%intNodeData)
51 if (
associated(string%conn)) &
52 deallocate (string%conn)
54 if (
associated(string%pNodes)) &
55 deallocate (string%pNodes)
57 if (
associated(string%pElems)) &
58 deallocate (string%pElems)
60 if (
associated(string%cNodes)) &
61 deallocate (string%cNodes)
63 if (
associated(string%otherID)) &
64 deallocate (string%otherID)
66 if (
associated(string%nte)) &
67 deallocate (string%nte)
69 if (
associated(string%subStr)) &
70 deallocate (string%subStr)
72 if (
associated(string%elemUsed)) &
73 deallocate (string%elemUsed)
75 if (
associated(string%xZipNodeUsed)) &
76 deallocate (string%xZipNodeUsed)
78 if (
associated(string%tris)) &
79 deallocate (string%tris)
81 if (
associated(string%surfCellID)) &
82 deallocate (string%surfCellID)
93 string%x => string%nodeData(1:3, :)
94 string%norm => string%nodeData(4:6, :)
95 string%perpNorm => string%nodeData(7:9, :)
96 string%h => string%nodeData(10, :)
98 string%ind => string%intNodeData(1, :)
99 string%cluster => string%intNodeData(2, :)
100 string%family => string%intNodeData(3, :)
114 integer(kind=intType) :: nElems, nNodes, curElem, nString, iStart, i, firstElem
125 nelems = master%nElems
126 nnodes = master%nNodes
127 allocate (master%elemUsed(nelems), master%subStr(2, nelems), &
128 master%cNodes(2, nnodes))
134 do while (curelem < master%nElems)
137 istart = master%conn(1, curelem)
138 nelems = master%nte(1, istart)
143 firstelem = master%nte(2, istart)
144 master%subStr(1, 1) = firstelem
145 call dochain(master, istart, 1)
151 firstelem = master%nte(3, istart)
155 if (master%elemUsed(firstelem) == 0)
then
157 master%subStr(2, 1) = firstelem
158 call dochain(master, istart, 2)
169 if (nstring == 0)
then
172 stringsll%next => stringsll
176 str%next%next => stringsll
178 nstring = nstring + 1
186 do while ((master%elemUsed(curelem) == 1) .and. (curelem < master%nElems))
187 curelem = curelem + 1
193 allocate (strings(nstring))
196 do while (i < nstring)
214 integer(kind=intType) :: nStrings
216 logical,
intent(in) :: debugZipper
220 real(kind=realtype) :: cutoff
221 integer(kind=intType) :: i, j, nZipped
230 str%isPocket = .true.
232 if (str%otherID(1, j) /= -1)
then
233 str%isPocket = .false.
237 if (.not. str%isPocket)
then
238 zipperloop:
do j = 1, 5
244 call selfzip(strings(i), cutoff, nzipped)
245 if (nzipped == 0)
then
272 real(kind=realtype) :: minedge
273 integer(kind=intType) :: nUnqiue, i, n1, n2, nUnique, idx
274 integer(kind=intType),
dimension(:),
allocatable :: link
275 real(kind=realtype),
dimension(:, :),
allocatable :: uniquenodes
276 real(kind=realtype),
dimension(:, :),
pointer :: nodedataptr
277 integer(kind=intType),
dimension(:, :),
pointer :: intNodeDataPtr
278 integer(kind=intType),
dimension(:),
allocatable :: normCounter
279 real(kind=realtype),
dimension(:, :),
allocatable :: uniquenorms
284 minedge = huge(1.0d0)
286 do i = 1, string%nElems
287 n1 = string%conn(1, i)
288 n2 = string%conn(2, i)
289 minedge = min(minedge,
mynorm2(string%x(:, n1) - string%x(:, n2)))
292 allocate (link(string%nNodes), uniquenodes(3, string%nNodes))
294 call pointreduce(string%x, string%nNodes, minedge / 1000.0, uniquenodes, link, nunique)
298 allocate (normcounter(nunique), uniquenorms(3, nunique))
299 normcounter(:) =
zero
300 uniquenorms(:, :) =
zero
302 do i = 1, string%nNodes
304 uniquenorms(:, idx) = uniquenorms(:, idx) + string%nodeData(4:6, i)
305 normcounter(idx) = normcounter(idx) + 1
309 do i = 1, string%nNodes
311 string%nodeData(4:6, i) = uniquenorms(:, idx) / normcounter(idx)
313 deallocate (normcounter, uniquenorms)
317 do i = 1, string%nElems
318 string%conn(1, i) = link(string%conn(1, i))
319 string%conn(2, i) = link(string%conn(2, i))
324 nodedataptr => string%nodeData
325 intnodedataptr => string%intNodeData
326 allocate (string%nodeData(10, nunique), string%intNodeData(3, nunique))
331 do i = 1, string%nNodes
332 string%nodeData(:, link(i)) = nodedataptr(:, i)
333 string%intNodeData(:, link(i)) = intnodedataptr(:, i)
335 string%nNodes = nunique
338 deallocate (nodedataptr, intnodedataptr, link, uniquenodes)
356 integer(kind=intType) :: i, j, ii, jj, n(2), m(2), curelem, ndup
357 integer(kind=intType),
dimension(string%nElems) :: duplicated
358 integer(kind=intType),
dimension(:, :),
pointer :: tmpconn
359 logical :: duplicateelement
361 allocate (string%nte(3, string%nNodes))
365 do i = 1, string%nElems
367 n = string%conn(:, i)
372 duplicateelement = .false.
375 do j = 1, string%nte(1, n(jj))
376 curelem = string%nte(j + 1, n(jj))
378 m = string%conn(:, curelem)
380 if (m(1) == n(1) .and. m(2) == n(2))
then
381 duplicateelement = .true.
382 else if (m(1) == n(2) .and. m(2) == n(1))
then
386 call terminate(
"makeBoundaryString",
"Inconsistent duplicate edge.")
391 if (.not. duplicateelement)
then
393 string%nte(1, n(jj)) = string%nte(1, n(jj)) + 1
394 ii = string%nte(1, n(jj))
395 string%nte(ii + 1, n(jj)) = i
405 ndup = sum(duplicated)
407 tmpconn => string%conn
409 allocate (string%conn(2, string%nElems - ndup))
412 do i = 1, string%nElems
413 if (duplicated(i) == 0)
then
415 string%conn(:, j) = tmpconn(:, i)
421 string%nElems = string%nElems - ndup
429 deallocate (string%nte)
440 integer(kind=intType),
intent(in) :: iStart, iSub
443 integer(Kind=intType) :: i, j, jj, c, n1, n2, curNode, nextNode
444 integer(Kind=intType) :: elem1, elem2, curElem, nextElem
445 integer(kind=intType) :: N
455 curelem = master%subStr(isub, n)
458 master%elemUsed(curelem) = 1
461 n1 = master%conn(1, curelem)
462 n2 = master%conn(2, curelem)
464 if (n1 == curnode)
then
471 if (nextnode == istart)
then
477 c = master%nte(1, nextnode)
482 else if (c == 2)
then
484 elem1 = master%nte(2, nextnode)
485 elem2 = master%nte(3, nextnode)
487 if (elem1 == curelem)
then
496 master%subStr(isub, n) = nextelem
499 master%elemUsed(nextelem) = 1
505 master%nSubStr(isub) = n
516 integer(kind=intType),
intent(in) :: id
519 integer(kind=intType) :: i, j, n1, n2, k
520 integer(kind=intType),
dimension(:),
allocatable :: nodeUsed
529 s%nElems = p%nSubStr(1)
534 allocate (nodeused(p%nNodes))
538 n1 = p%conn(1, p%subStr(1, i))
539 n2 = p%conn(2, p%subStr(1, i))
540 if (nodeused(n1) == 0)
then
545 if (nodeused(n2) == 0)
then
557 if (s%nNodes == s%nElems)
then
558 s%isPeriodic = .true.
562 allocate (s%pElems(s%nElems), s%pNodes(s%nNodes))
565 s%pElems(i) = p%subStr(1, i)
572 if (nodeused(i) /= 0)
then
573 s%pNodes(nodeused(i)) = i
579 p%cNodes(:, s%pNodes(i)) = (/s%myID, i/)
586 allocate (s%nodeData(10, s%nNodes), s%intNodeData(3, s%nNodes))
592 s%nodeData(:, i) = p%nodeData(:, s%pNodes(i))
593 s%intNodeData(:, i) = p%intNodeData(:, s%pNodes(i))
597 allocate (s%conn(2, s%nElems))
600 s%conn(1, i) = nodeused(p%conn(1, s%pElems(i)))
601 s%conn(2, i) = nodeused(p%conn(2, s%pElems(i)))
607 deallocate (nodeused)
618 integer(kind=intType) :: N1, N2
624 s%subStr(2, 1:n2) = s%subStr(2, n2:1:-1)
627 s%subStr(2, n2 + 1:n2 + n1) = s%subStr(1, 1:n1)
630 s%subStr(1, 1:n1 + n2) = s%subStr(2, 1:n1 + n2)
631 s%nSubStr(1) = n1 + n2
644 integer(Kind=intType),
intent(out) :: nZipped
645 real(kind=realtype),
intent(in) :: cutoff
648 integer(kind=intType) :: i, j, k, N, ii, im1, ip1
649 logical :: lastNodeZippered, added
650 real(kind=realtype),
dimension(3) :: v1, v2, norm
651 real(kind=realtype) :: coscutoff, costheta, r2, v1nrm, v2nrm
652 integer(Kind=intType),
dimension(:),
allocatable :: nodeMap
653 type(kdtree2_result),
dimension(:),
allocatable :: results
660 allocate (results(25))
661 allocate (nodemap(s%nNodes))
664 coscutoff = cos(cutoff *
pi / 180)
669 if (s%isPeriodic)
then
684 if (s%isPeriodic .and. ii == n)
then
688 lastnodezippered = .false.
691 v1 = s%x(:, ip1) - s%x(:, ii)
692 v2 = s%x(:, im1) - s%x(:, ii)
698 if (dot_product(norm, s%norm(:, ii)) >
zero)
then
701 if (dot_product(s%norm(:, ip1), s%norm(:, im1)) > 0.80)
then
703 costheta = dot_product(v1, v2) / (v1nrm * v2nrm)
705 if (costheta > coscutoff)
then
711 nzipped = nzipped + 1
712 lastnodezippered = .true.
718 if (lastnodezippered)
then
737 deallocate (results, nodemap)
741 subroutine crosszip(str1, N1, N2, str2, N3, N4, debugZipper, failed)
749 integer(kind=intType) :: N1, N2, N3, N4
750 logical :: debugZipper, failed
753 integer(kind=intType) :: stepsA, stepsB, nStepsA, nStepsB
754 integer(kind=intType) :: nTriToAdd, ii, i, j, k, A, B, Ap, Bp
755 integer(kind=intType) :: aPrev, bPrev
756 real(kind=realtype),
dimension(3) :: pta, ptb, ptap, ptbp
758 real(kind=realtype),
dimension(3) :: aoff, boff, apoff, bpoff
759 real(kind=realtype),
dimension(3) :: norma, normb, normap, normbp
760 real(kind=realtype),
dimension(3) :: perpa, perpb, perpap, perpbp
763 real(kind=realtype),
dimension(3) :: trinorm1, quadnorm1
764 real(kind=realtype),
dimension(3) :: trinorm2, quadnorm2
765 logical :: aValid, bValid, advanceA, aPreferred, area1, area2
767 logical :: changeA, changeB
768 logical :: aValidPrev, bValidPrev, advanceAPrev, advanceBPrev
769 real(kind=realtype) :: sum1, sum2, h, dpa, dpb
771 real(kind=realtype),
parameter :: cutoff = 0.85 * 3
779 else if (n2 < n1)
then
780 nstepsa = n2 + str1%nNodes - n1
782 nstepsa = str1%nElems
787 nstepsb = n3 + str2%nNodes - n4
788 else if (n3 > n4)
then
791 nstepsb = str2%nElems
808 norma = str1%norm(:, a)
809 normb = str2%norm(:, b)
811 perpa = str1%perpNorm(:, a)
812 perpb = str2%perpNorm(:, b)
818 normap = str1%norm(:, ap)
819 normbp = str2%norm(:, bp)
820 perpap = str1%perpNorm(:, ap)
821 perpbp = str2%perpNorm(:, bp)
825 do while (ii < nstepsa + nstepsb)
837 if (
trioverlap(pta, ptb, ptap, str1, a, ap) .or. &
842 if (
trioverlap(pta, ptb, ptbp, str1, a, a) .or. &
876 if (area1 .eqv. .false.)
then
881 if (area2 .eqv. .false.)
then
924 call cross_prod(ptb - pta, ptap - pta, trinorm1)
925 trinorm1 = trinorm1 /
mynorm2(trinorm1)
928 sum1 = dot_product(trinorm1, norma) + dot_product(trinorm1, normb) + &
929 dot_product(trinorm1, normap)
931 call cross_prod(ptb - pta, ptbp - pta, trinorm2)
932 trinorm2 = trinorm2 /
mynorm2(trinorm2)
934 sum2 = dot_product(trinorm2, norma) + dot_product(trinorm2, normb) + &
935 dot_product(trinorm2, normbp)
938 if (avalid .and. bvalid .and. dot_product(trinorm1, trinorm2) < 0.8)
then
942 if (sum1 < cutoff .and. sum2 > cutoff)
then
945 else if (sum2 < cutoff .and. sum1 > cutoff)
then
948 else if (sum1 < cutoff .and. sum2 < cutoff)
then
950 if (sum1 > sum2)
then
964 sum1 = abs(
vecangle(pta - ptap, ptb - ptap)) + abs(
vecangle(ptbp - ptb, ptap - ptb))
965 sum2 = abs(
vecangle(pta - ptbp, ptb - ptbp)) + abs(
vecangle(ptbp - pta, ptap - pta))
967 if (sum1 > sum2)
then
991 if (avalid .and. .not. bvalid)
then
994 call addtri(a, str1, b, str2, ap, str1)
998 str1%xZipNOdeUsed(a) = 1
999 str1%xZipNOdeUsed(ap) = 1
1000 str2%xZipNOdeUsed(b) = 1
1002 else if (bvalid .and. .not. avalid)
then
1006 call addtri(a, str1, b, str2, bp, str2)
1007 str1%xZipNOdeUsed(a) = 1
1008 str2%xZipNOdeUsed(b) = 1
1009 str2%xZipNOdeUsed(bp) = 1
1014 else if (avalid .and. bvalid)
then
1017 if (apreferred)
then
1019 call addtri(a, str1, b, str2, ap, str1)
1021 str1%xZipNOdeUsed(a) = 1
1022 str1%xZipNOdeUsed(ap) = 1
1023 str2%xZipNOdeUsed(b) = 1
1030 call addtri(a, str1, b, str2, bp, str2)
1031 str1%xZipNOdeUsed(a) = 1
1032 str2%xZipNOdeUsed(b) = 1
1033 str2%xZipNOdeUsed(bp) = 1
1044 if (avalidprev .and. bvalidprev)
then
1054 p%nTris = p%nTris - 1
1055 p%nEdges = p%nEdges - 3
1060 if (advanceaprev)
then
1063 avalidprev = .false.
1067 call addtri(aprev, str1, b, str2, bp, str2)
1079 norma = str1%norm(:, a)
1080 perpa = str1%perpNorm(:, a)
1091 ptbp = str2%x(:, bp)
1092 normbp = str2%norm(:, bp)
1093 perpbp = str2%perpNorm(:, bp)
1096 advancebprev = .true.
1097 advanceaprev = .false.
1102 bvalidprev = .false.
1105 call addtri(a, str1, bprev, str2, ap, str1)
1117 normb = str2%norm(:, b)
1118 perpb = str2%perpNorm(:, b)
1129 ptap = str1%x(:, ap)
1130 normap = str1%norm(:, ap)
1131 perpap = str1%perpNorm(:, ap)
1133 advanceaprev = .true.
1134 advancebprev = .false.
1141 if (debugzipper)
then
1142 print *,
'Saved cross zip from bad front.'
1161 if (advancea .and. .not. advanceb)
then
1176 ptap = str1%x(:, ap)
1177 normap = str1%norm(:, ap)
1178 perpap = str1%perpNorm(:, ap)
1180 else if (advanceb .and. .not. advancea)
then
1195 ptbp = str2%x(:, bp)
1196 normbp = str2%norm(:, bp)
1197 perpbp = str2%perpNorm(:, bp)
1203 advanceaprev = advancea
1204 advancebprev = advanceb
1216 integer(kind=intType),
intent(in) :: i
1217 logical,
intent(in) :: pos
1221 if (stepsa == nstepsa)
then
1226 if (str%isPeriodic)
then
1236 if (stepsb == nstepsb)
then
1241 if (str%isPeriodic)
then
1257 real(kind=realtype),
dimension(3),
intent(in) :: vec1, vec2
1261 real(kind=realtype),
dimension(3) :: veca, vecb
1266 vecangle = acos(dot_product(veca, vecb))
1275 integer(kind=intType),
intent(in) :: a, b
1279 integer(kind=intType) :: e1, e2, e3, e4
1281 if (str%nte(1, a) == 1)
then
1289 if (str%nte(1, b) == 1)
then
1300 if (e1 == e3 .or. e1 == e4)
then
1315 real(kind=realtype),
intent(in),
dimension(3) :: pt1, pt2, pt3
1316 real(kind=realtype) ::
triarea
1319 real(kind=realtype),
dimension(3) :: norm
1337 integer(kind=intType),
intent(in) :: a, b, c
1342 integer(kind=intType) :: mn1, mn2, mn3
1345 p%nTris = p%nTris + 1
1352 p%tris(:, p%nTris) = (/mn1, mn2, mn3/)
1357 p%nEdges = p%nEdges + 1
1358 p%edges(p%nEdges)%n1 = mn1
1359 p%edges(p%nEdges)%n2 = mn2
1362 p%nEdges = p%nEdges + 1
1363 p%edges(p%nEdges)%n1 = mn2
1364 p%edges(p%nEdges)%n2 = mn3
1367 p%nEdges = p%nEdges + 1
1368 p%edges(p%nEdges)%n1 = mn3
1369 p%edges(p%nEdges)%n2 = mn1
1379 integer(kind=intType),
intent(in) :: nStrings
1380 type(
oversetstring),
intent(inout),
target :: p, strings(nStrings)
1382 logical,
intent(in) :: debugZipper
1384 integer(kind=intType) :: i, iStart, iEnd, jStart, jEnd, iStart_j, iEnd_j
1385 integer(kind=intType) :: curOtherID, iString, ii, nextI, curIStart, nIElems_j
1386 integer(kind=intType) :: nIElemsBeg, nJElemsBeg, nElem1, nElem2
1387 integer(kind=intType) :: iStart_orig, iEnd_orig, jStart_orig, jEnd_orig
1388 logical :: fullLoop1, fullLoop2, dummy, failed
1397 allocate (s%XzipNodeUsed(s%nNodes))
1401 strloop:
do istring = 1, nstrings
1404 if (strings(istring)%isPocket)
then
1409 s1 => strings(istring)
1413 do while (curistart > 0)
1415 if (debugzipper)
then
1416 print *,
'------------------------------------------------'
1417 print *,
'Starting string ', s1%myid,
'at index ', curistart
1418 print *,
'------------------------------------------------'
1423 curotherid = s1%otherID(1, istart)
1425 if (curotherid == -1)
then
1426 print *,
'*************************************************************************'
1427 print *,
'Error during makeCrossZip: Point ', istart,
'does not have a matching point'
1428 print *,
'Position: ', s1%x(:, istart)
1429 print *,
'*************************************************************************'
1434 s2 => strings(curotherid)
1435 jstart = s1%otherID(2, istart)
1440 call tracematch(s1, istart, .false., curotherid, iend, fullloop1)
1442 if (.not. fullloop1)
then
1447 call tracematch(s1, istart, .true., curotherid, iend, dummy)
1456 call tracematch(s2, jstart, .true., s1%myID, jend, fullloop2)
1460 if (jstart == jend .and. .not. fullloop2 .and. &
1461 s2%otherID(1, jstart) /= s1%myID)
then
1462 s1%xZipNodeUsed(curistart) = 1
1467 if (.not. fullloop2)
then
1469 call tracematch(s2, jstart, .false., s1%myID, jend, dummy)
1472 if ((istart == iend .and. .not. fullloop1) .or. &
1473 (jstart == jend .and. .not. fullloop2))
then
1476 s1%xZipNodeUsed(curistart) = 1
1481 if (debugzipper)
then
1482 print *,
'Initial Range s1:', istart, iend, fullloop1
1483 print *,
'Initial Range s2:', jstart, jend, fullloop2
1487 istart_orig = istart
1489 jstart_orig = jstart
1492 if ((istart == iend .and. fullloop1) .and. &
1493 (jstart == jend .and. fullloop2))
then
1500 else if ((istart == iend .and. fullloop1) .and. .not. fullloop2)
then
1503 istart = s2%otherID(2, jstart)
1504 iend = s2%otherID(2, jend)
1506 else if ((jstart == jend .and. fullloop2) .and. .not. fullloop1)
then
1509 jstart = s1%otherID(2, istart)
1510 jend = s1%otherID(2, iend)
1522 istart_j = s2%otherID(2, jstart)
1523 iend_j = s2%otherID(2, jend)
1531 if (istart_j /= istart)
then
1535 do ii = 1, nielemsbeg
1537 if (i == istart_j)
then
1544 if (iend_j /= iend)
then
1548 do ii = 1, nielemsbeg
1550 if (i == iend_j)
then
1559 jstart = s1%otherID(2, istart)
1560 jend = s1%otherID(2, iend)
1564 if (debugzipper)
then
1565 print *,
'Zipping string: ', s1%myid,
' with ', s2%myid
1566 print *,
's1 range:', istart, iend
1567 print *,
's2 range:', jstart, jend
1574 if (.not. fullloop1)
then
1576 if (istart == iend)
then
1581 if (.not. fullloop2)
then
1583 if (jstart == jend)
then
1588 if (nelem1 > 0 .and. nelem2 > 0)
then
1590 call crosszip(s1, istart, iend, s2, jstart, jend, debugzipper, failed)
1594 if (.not. failed)
then
1631 nodeloop:
do i = 1, s%nNodes
1632 if (s%xZipNodeUsed(i) == 0)
then
1643 integer(kind=intType),
intent(in) :: i
1649 if (i == s%nNodes)
then
1650 if (s%isPeriodic)
then
1660 if (s%xZipNodeUsed(
nextnode) == 1)
then
1669 integer(kind=intType),
intent(in) :: i
1675 if (i == s%nNodes)
then
1676 if (s%isPeriodic)
then
1689 integer(kind=intType),
intent(in) :: i
1695 if (s%isPeriodic)
then
1705 if (s%xZipNodeUsed(
prevnode) == 1)
then
1721 integer(kind=intType),
intent(in) :: iStart, checkID
1722 logical,
intent(in) :: pos
1723 integer(kind=intType),
intent(out) :: iEnd
1724 logical,
intent(out) :: fullLoop
1727 integer(kind=intType) :: i, nextI
1738 if (nexti == i .or. s%otherID(1, nexti) /= checkid)
then
1747 if (i == istart)
then
1761 integer(kind=intType),
intent(in) :: N1, N2
1762 logical,
intent(in) :: pos
1765 integer(kind=intType) :: nSteps, i, nextI
1770 else if (n2 < n1)
then
1771 nsteps = n2 + s%nNodes - n1
1777 nsteps = n1 + s%nNodes - n2
1778 else if (n1 > n2)
then
1785 s%xZipNodeUsed(n1) = 1
1794 s%xZipNodeUsed(nexti) = 1
1805 integer(kind=intType),
intent(in) :: n1, n2
1809 if (.not. s%isPeriodic)
then
1819 else if (n2 > n1)
then
1827 else if (n1 > n2)
then
1846 integer(kind=intType),
intent(in) :: nStrings
1849 logical,
intent(in) :: debugZipper
1852 integer(kind=intType) :: i, j, nsum1, nsum2, ndiff1, ndiff2, ipedge, icur
1853 integer(kind=intType) :: n1, n2, npolyEdges
1854 integer(kind=intType) :: nNodes1, nNodes2, cn1, cn2, str1, str2
1855 type(
oversetedge),
allocatable,
dimension(:) :: polyEdges
1858 integer(kind=intType) :: npocketEdges, nFullStrings, nNodes
1859 integer(kind=intType) :: ip, curElem, nElems, iStart, firstElem
1860 type(
oversetstring),
allocatable,
dimension(:),
target :: pocketStringsArr
1871 allocate (polyedges(p%nEdges))
1877 do while (i <= p%nEdges)
1879 if (i == p%nEdges)
then
1882 npolyedges = npolyedges + 1
1883 polyedges(npolyedges) = e1
1896 str1 = p%cNodes(1, e1%n1)
1897 cn1 = p%cNodes(2, e1%n1)
1898 nnodes1 = strings(str1)%nNodes
1900 str2 = p%cNodes(1, e1%n2)
1901 cn2 = p%cNodes(2, e1%n2)
1902 nnodes2 = strings(str2)%nNodes
1904 if (str1 /= str2)
then
1905 if (.not. strings(str1)%isperiodic .and. &
1906 .not. strings(str2)%isperiodic .and. &
1907 (cn1 == 1 .or. cn1 == nnodes1) .and. (cn2 == 1 .or. cn2 == nnodes2))
then
1915 nsum1 = e1%n1 + e1%n2
1916 nsum2 = e2%n1 + e2%n2
1918 ndiff1 = e1%n2 - e1%n1
1919 ndiff2 = e2%n2 - e2%n1
1921 if (nsum1 == nsum2 .and. ndiff1 + ndiff2 == 0)
then
1927 npolyedges = npolyedges + 1
1928 polyedges(npolyedges) = e1
1935 pocketmaster%myID = 88
1936 pocketmaster%nElems = npolyedges
1937 pocketmaster%nNodes = npolyedges * 2
1938 pocketmaster%nEdges = 0
1939 allocate (pocketmaster%nodeData(10, 2 * npolyedges), &
1940 pocketmaster%intNodeData(3, 2 * npolyedges), &
1941 pocketmaster%conn(2, npolyedges))
1944 do i = 1, npolyedges
1945 pocketmaster%nodeData(:, 2 * i - 1) = p%nodeData(:, polyedges(i)%n1)
1946 pocketmaster%intNodeData(:, 2 * i - 1) = p%intNodeData(:, polyedges(i)%n1)
1948 pocketmaster%nodeData(:, 2 * i) = p%nodeData(:, polyedges(i)%n2)
1949 pocketmaster%intNodeData(:, 2 * i) = p%intNodeData(:, polyedges(i)%n2)
1950 pocketmaster%conn(:, i) = (/2 * i, 2 * i - 1/)
1964 nelems = pocketmaster%nElems
1965 nnodes = pocketmaster%nNodes
1966 allocate (pocketmaster%elemUsed(nelems), pocketmaster%subStr(2, nelems), &
1967 pocketmaster%cNodes(2, nnodes))
1969 pocketmaster%cNodes = 0
1970 pocketmaster%elemUsed = 0
1974 do while (curelem < pocketmaster%nElems)
1977 istart = pocketmaster%conn(1, curelem)
1978 nelems = pocketmaster%nte(1, istart)
1980 firstelem = pocketmaster%nte(2, istart)
1981 pocketmaster%subStr(1, 1) = firstelem
1982 call dochain(pocketmaster, istart, 1)
1990 if (nfullstrings == 0)
then
1991 allocate (stringsll)
1993 stringsll%next => stringsll
1997 str%next%next => stringsll
1999 nfullstrings = nfullstrings + 1
2007 do while ((pocketmaster%elemUsed(curelem) == 1) .and. &
2008 (curelem < pocketmaster%nElems))
2009 curelem = curelem + 1
2014 allocate (pocketstringsarr(nfullstrings))
2017 do while (i < nfullstrings)
2019 pocketstringsarr(i) = str
2026 allocate (pocketmaster%tris(3, 10 * pocketmaster%nElems))
2027 allocate (pocketmaster%edges(4 * pocketmaster%nElems))
2028 pocketmaster%nTris = 0
2033 if (debugzipper)
then
2034 open (unit=101, file=
"strings_pocket.dat", form=
'formatted')
2035 write (101, *)
'TITLE = "PocketStrings Data" '
2037 write (101, *)
'Variables = "X" "Y" "Z" "Nx" "Ny" "Nz" "Vx" "Vy" "Vz" "ind" &
2038 &"gapID" "gapIndex" "otherID" "otherIndex" "ratio"'
2039 do i = 1, nfullstrings
2041 allocate (pocketstringsarr(i)%otherID(2, pocketstringsarr(i)%nNodes))
2042 pocketstringsarr(i)%otherID = -1
2052 do i = 1, nfullstrings
2053 if (debugzipper)
then
2054 print *,
'Pocket Zipping String ', i,
' of ', nfullstrings
2056 pocketziploop:
do while (pocketstringsarr(i)%nNodes > 2)
2060 end do pocketziploop
2064 do i = 1, nfullstrings
2067 deallocate (pocketstringsarr, polyedges)
2083 integer(kind=intType) :: i, j, k, ii, im1, ip1, N
2084 integer(kind=intType) :: nNodes, nElems, iimin
2085 real(kind=realtype),
dimension(3) :: v1, v2, norm, c
2086 real(kind=realtype) :: coscutoff, costheta, r2, v1nrm, v2nrm, costhetamax
2087 real(kind=realtype) :: dp, dpmax
2089 integer(Kind=intType),
dimension(:),
allocatable :: nodeMap, badNode
2090 type(kdtree2_result),
dimension(:),
allocatable :: results
2091 logical :: added, iiMinSet
2092 real(kind=realtype),
parameter :: fact = 0.95_realtype
2094 allocate (results(25), nodemap(n), badnode(n))
2106 call addtri(ip1, s, ii, s, im1, s)
2116 nodeloop1:
do ii = 1, n
2118 if (badnode(ii) == 1)
then
2126 v1 = s%x(:, im1) - s%x(:, ii)
2127 v2 = s%x(:, ip1) - s%x(:, ii)
2132 dpmax = max(dpmax, dot_product(norm, s%norm(:, ii)))
2137 costhetamax = -
large
2138 nodeloop2:
do ii = 1, n
2140 if (badnode(ii) == 1)
then
2148 v1 = s%x(:, im1) - s%x(:, ii)
2149 v2 = s%x(:, ip1) - s%x(:, ii)
2154 dp = dot_product(norm, s%norm(:, ii))
2155 if (dp > dpmax * fact)
then
2156 costheta = dot_product(v1, v2) / (v1nrm * v2nrm)
2157 if (costheta > costhetamax)
then
2158 costhetamax = costheta
2182 print *,
'Problem with pocket zipper. Somehow we were not able to find "&
2183 &"node to add a triangle on. This should not happen. Contact the "&
2192 deallocate (nodemap, badnode, results)
2197 integer(kind=intType) :: ii,
nextnode
2206 integer(kind=intType) :: ii,
prevnode
2223 real(kind=realtype),
intent(out) :: area
2226 integer(kind=intType) :: i, n1, n2, n3
2227 real(kind=realtype),
dimension(3) :: v1, v2, norm
2230 do i = 1, master%nTris
2231 n1 = master%tris(1, i)
2232 n2 = master%tris(2, i)
2233 n3 = master%tris(3, i)
2235 v1 = master%x(:, n2) - master%x(:, n1)
2236 v2 = master%x(:, n3) - master%x(:, n1)
2250 real(kind=realtype),
dimension(3),
intent(in) :: pt1, pt2, pt3
2251 integer(kind=intType),
intent(in) :: i1, i2
2256 integer(kind=intType) :: i
2257 real(kind=realtype) :: trinorm(3)
2262 call cross_prod(pt2 - pt1, pt3 - pt1, trinorm)
2263 trinorm = trinorm /
mynorm2(trinorm)
2266 do i = 1, str%nNodes
2267 if (i /= i1 .and. i /= i2)
then
2268 if (dot_product(str%norm(:, i), trinorm) > 0.8)
then
2290 integer(kind=intType),
dimension(:),
intent(inout) :: nodemap
2293 integer(kind=intType) :: nnodes, nelems, nremoved, i, j
2294 real(kind=realtype),
dimension(:, :),
pointer :: nodedatatmp
2295 integer(kind=intType),
dimension(:, :),
pointer :: conntmp, intnodedatatmp
2296 integer(kind=intType),
dimension(:),
pointer :: pnodestmp
2306 nodedatatmp => s%nodeData
2307 intnodedatatmp => s%intNodeData
2309 pnodestmp => s%pNodes
2319 if (nodemap(i) == 1)
then
2323 nremoved = nremoved + 1
2331 s%p%cNodes(:, s%pNodes(i)) = (/s%myID, nodemap(i)/)
2336 s%nNodes = s%nNodes - nremoved
2337 s%nElems = s%nElems - nremoved
2339 allocate (s%nodeData(10, s%nNodes), s%intNodeData(3, s%nNodes), &
2340 s%pNodes(s%nNodes), s%conn(2, s%nElems))
2346 if (nodemap(i) /= 0)
then
2347 s%nodeData(:, nodemap(i)) = nodedatatmp(:, i)
2348 s%intNodeData(:, nodemap(i)) = intnodedatatmp(:, i)
2349 s%pNodes(nodemap(i)) = pnodestmp(i)
2355 s%conn(:, i) = (/i, i + 1/)
2358 if (s%isPeriodic)
then
2359 s%conn(2, s%nElems) = 1
2363 deallocate (nodedatatmp, intnodedatatmp, conntmp, pnodestmp)
2366 if (s%nNodes >= 3)
then
2383 integer(kind=intType),
intent(in) :: im1, ii, ip1
2384 integer(kind=intType),
intent(inout),
dimension(:) :: nodeMap
2386 logical,
intent(out) :: added
2388 real(kind=realtype) :: r2
2389 real(kind=realtype),
dimension(3) :: v1, v2, norm, c
2390 integer(kind=intType) :: nFound, nalloc, idx, k, j, i
2391 logical :: overlapFound, inTri
2411 c =
half * (s%x(:, ip1) + s%x(:, im1))
2412 r2 = (c(1) - s%x(1, ii))**2 + (c(2) - s%x(2, ii))**2 + (c(3) - s%x(3, ii))**2
2414 r2 = max(r2, (s%x(1, ip1) - s%x(1, im1))**2 + (s%x(2, ip1) - s%x(2, im1))**2 + &
2415 (s%x(3, ip1) - s%x(3, im1))**2)
2419 nalloc =
size(results)
2421 if (nfound < nalloc)
then
2426 deallocate (results)
2428 allocate (results(nalloc))
2433 overlapfound = .false.
2434 nodefoundloop:
do k = 1, nfound
2439 idx = results(k)%idx
2441 notpartoftriangle:
if (idx /= s%pNodes(im1) .and. &
2442 idx /= s%pNodes(ii) .and. idx /= s%pNodes(ip1))
then
2446 if (dot_product(s%norm(:, ii), s%p%norm(:, idx)) >
zero)
then
2450 s%p%x(:, idx), intri)
2454 overlapfound = .true.
2458 end if notpartoftriangle
2459 end do nodefoundloop
2461 if (.not. overlapfound)
then
2468 call addtri(ip1, s, ii, s, im1, s)
2484 integer(kind=intType),
intent(out) :: i, j
2485 real(kind=realtype) :: mindist, dist
2486 integer(kind=intType) :: ii
2491 do ii = 1, s1%nNodes
2495 if (s2%otherID(2, s1%otherID(2, ii)) == ii)
then
2497 dist =
mynorm2(s1%x(:, ii) - s2%x(:, s1%otherID(2, ii)))
2499 if (dist < mindist)
then
2502 j = s1%otherID(2, ii)
2518 integer(kind=intType),
intent(in) :: nStrings
2520 logical,
intent(in) :: debugZipper
2523 integer(kind=intType) :: i, j, k, idx, oid(4)
2524 integer(kind=intType) :: nAlloc, nUnique, nSearch
2527 logical :: checkLeft, checkRight, concave
2528 logical :: checkLeft2, checkRight2, concave2
2529 logical :: leftOK, rightOK, isEndNode
2530 real(kind=realtype),
dimension(3) :: xj, xjp1, xjm1, normj
2531 real(kind=realtype),
dimension(3) :: xk, xkp1, xkm1, normk
2532 real(kind=realtype),
dimension(3) :: mypt, otherpt, enorm
2533 real(kind=realtype) :: fact, dstar, curdist, mindist, edgelength
2534 integer(kind=intTYpe) :: otherID, otherIndex, closestOtherIndex, closestOtherString
2535 integer(kind=intType) :: id, index
2536 real(kind=realtype) :: timea, pt(3), v(3), costheta, cutoff, dist, maxh, ratio
2538 if (nstrings == 0)
then
2545 allocate (results(nalloc))
2546 master => strings(1)%p
2553 if (str%isPocket)
then
2558 if (
associated(str%otherID))
then
2559 deallocate (str%otherID)
2562 allocate (str%otherID(2, str%nNodes))
2566 nodeloop:
do j = 1, str%nNodes
2570 nsearch = min(nalloc, master%nNodes)
2575 call getnodeinfo(str, j, checkleft, checkright, concave, &
2576 xj, xjm1, xjp1, normj)
2578 if (.not. (checkleft .eqv. checkright))
then
2588 closestotherindex = -1
2595 innerloop:
do k = 1, nsearch
2605 curdist = sqrt(results(k)%dis)
2606 idx = results(k)%idx
2607 pt = master%x(:, idx)
2616 if (curdist > mindist)
then
2625 if (master%cNodes(1, idx) == str%myID)
then
2634 if (master%cNodes(2, idx) == 0)
then
2641 if (closestotherindex == -1)
then
2642 closestotherstring = master%cNodes(1, idx)
2643 closestotherindex = master%cNodes(2, idx)
2654 xj, xjm1, xjp1, normj))
then
2663 otherid = master%cNodes(1, idx)
2664 otherindex = master%cNodes(2, idx)
2666 call getnodeinfo(strings(otherid), otherindex, checkleft2, &
2667 checkright2, concave2, xk, xkm1, xkp1, normk)
2670 checkright2, xk, xkm1, xkp1, normk))
then
2699 if (otherid /= closestotherstring)
then
2701 strings(closestotherstring), xj, normj, pt))
then
2711 if (checkright2 .eqv. checkleft2)
then
2728 costheta = abs(dot_product(normj, v))
2731 dstar = curdist / (max(1 - costheta, 1e-6))
2733 if (dstar < mindist)
then
2736 str%otherID(:, j) = master%cNodes(:, idx)
2741 if (nsearch == master%Nnodes)
then
2747 nsearch = nsearch * 2
2748 nsearch = min(nsearch, master%nNodes)
2749 if (nsearch > nalloc)
then
2750 deallocate (results)
2752 allocate (results(nalloc))
2762 do j = 3, str%nNodes - 2
2763 if (str%otherID(1, j) == -1)
then
2765 oid(1) = str%otherID(1, j - 2)
2766 oid(2) = str%otherID(1, j - 1)
2767 oid(3) = str%otherID(1, j + 1)
2768 oid(4) = str%otherID(1, j + 2)
2770 if (oid(1) /= -1 .and. &
2771 oid(1) == oid(2) .and. &
2772 oid(1) == oid(3) .and. &
2773 oid(1) == oid(4))
then
2775 if (debugzipper)
then
2776 print *,
'****************************************************************'
2777 print *,
'Warning: Fixing a bad association on string ', i,
'at index', j
2778 print *,
'****************************************************************'
2784 str%otherID(1, j) = oid(1)
2789 str%otherID(2, j) = str%otherID(2, j - 1)
2804 integer(kind=intType),
intent(in) :: fileID, n
2807 integer(kind=intType) :: i, j, id, index
2808 real(kind=realtype),
dimension(3) :: mypt, otherpt, vec
2809 real(kind=realtype) :: maxh, dist, ratio
2811 character(80) :: zoneName
2813 write (zonename,
"(a,I5.5)")
"Zone T=gap_", str%myID
2814 write (fileid, *) trim(zonename)
2816 write (fileid, *)
"Nodes = ", str%nNodes,
" Elements= ", str%nElems,
" ZONETYPE=FELINESEG"
2817 write (fileid, *)
"DATAPACKING=BLOCK"
2821 do i = 1, str%nNodes
2822 write (fileid,
sci12) str%x(j, i)
2828 do i = 1, str%nNodes
2829 write (fileid,
sci12) str%norm(j, i)
2835 do i = 1, str%nNodes
2837 id = str%otherID(1, i)
2839 index = str%otherID(2, i)
2840 otherpt = strings(id)%x(:, index)
2841 vec = otherpt - mypt
2846 write (fileid,
sci12) vec(j)
2851 do i = 1, str%nNodes
2852 write (fileid,
sci12) real(str%ind(i))
2856 do i = 1, str%nNodes
2857 write (fileid,
sci12) real(str%myID)
2861 do i = 1, str%nNodes
2862 write (fileid,
sci12) real(i)
2865 if (
associated(str%otherID))
then
2867 do i = 1, str%nNodes
2868 write (fileid,
sci12) real(str%otherID(1, i))
2872 do i = 1, str%nNodes
2873 write (fileid,
sci12) real(str%otherID(2, i))
2876 do i = 1, 2 * str%nNodes
2881 do i = 1, str%nNodes
2883 id = str%otherID(1, i)
2885 index = str%otherID(2, i)
2886 otherpt = strings(id)%x(:, index)
2887 dist =
mynorm2(mypt - otherpt)
2888 maxh = max(str%h(i), strings(id)%h(index))
2894 write (fileid,
sci12) ratio
2897 do i = 1, str%nElems
2898 write (fileid,
int5) str%conn(1, i), str%conn(2, i)
2911 integer(kind=intType),
intent(in) :: fileID
2912 integer(kind=intType) :: i, j, id, index
2913 real(kind=realtype),
dimension(3) :: mypt, otherpt, vec
2914 real(kind=realtype) :: maxh, dist, ratio
2916 character(80) :: zoneName
2918 write (zonename,
"(a,I5.5)")
"Zone T=gap_", str%myID
2919 write (fileid, *) trim(zonename)
2921 write (fileid, *)
"Nodes = ", str%nNodes,
" Elements= ", str%nElems,
" ZONETYPE=FELINESEG"
2922 write (fileid, *)
"DATAPACKING=BLOCK"
2926 do i = 1, str%nNodes
2927 write (fileid,
sci12) str%x(j, i)
2931 do i = 1, str%nElems
2932 write (fileid,
int5) str%conn(1, i), str%conn(2, i)
2944 integer(kind=intType),
intent(in) :: startTri, endTri
2945 character(*) :: fileName
2946 integer(kind=intType) :: i, j
2947 character(80) :: zoneName
2949 open (unit=101, file=trim(filename), form=
'formatted')
2950 write (101, *)
'TITLE = "Triangles"'
2951 write (101, *)
'Variables = "X", "Y", "Z"'
2953 write (zonename,
"(a,I5.5)")
"Zone T=triangles_", string%myID
2954 write (101, *) trim(zonename)
2956 write (101, *)
"Nodes = ", string%nNodes,
" Elements= ", (endtri - starttri + 1),
" ZONETYPE=FETRIANGLE"
2957 write (101, *)
"DATAPACKING=POINT"
2960 do i = 1, string%nNodes
2962 write (101,
sci12, advance=
'no') string%x(j, i)
2967 do i = starttri, endtri
2968 write (101,
"(*(I7))") string%tris(1, i), string%tris(2, i), string%tris(3, i)
2982 integer(kind=intType) :: i, j
2984 open (unit=101, file=
"debug.zipper", form=
'formatted')
2985 write (101, *) str%nNodes
2986 write (101, *) str%nElems
2987 do i = 1, str%nNodes
2989 write (101, *) str%nodeData(j, i)
2993 do i = 1, str%nElems
2995 write (101, *) str%conn(j, i)
2999 do i = 1, str%nNodes
3001 write (101, *) str%intNodeData(j, i)
3015 character(*),
intent(in) :: fileName
3017 integer(kind=intType) :: i, j
3019 open (unit=101, file=filename, form=
'formatted')
3020 read (101, *) str%nNodes
3021 read (101, *) str%nElems
3024 allocate (str%nodeData(10, str%nNodes))
3025 allocate (str%conn(2, str%nElems))
3026 allocate (str%intNodeData(3, str%nNodes))
3028 do i = 1, str%nNodes
3030 read (101, *) str%nodeData(j, i)
3034 do i = 1, str%nElems
3036 read (101, *) str%conn(j, i)
3040 do i = 1, str%nNodes
3042 read (101, *) str%intNodeData(j, i)
3056 real(kind=realtype),
dimension(3),
intent(in) :: x1, x2, x3, pt
3057 logical,
intent(out) :: inTri
3070 real(kind=realtype),
dimension(3) :: p1, p2, a, b, cp1, cp2
3075 if (dot_product(cp1, cp2) >=
zero)
then
3086 real(kind=realtype),
intent(in),
dimension(3) :: p1, p2, p3, norm
3087 real(kind=realtype),
dimension(3) :: n
3091 if (dot_product(n, norm) >
zero)
then
3098 subroutine getnodeinfo(str, j, checkLeft, checkRight, concave, xj, xjm1, xjp1, normj)
3105 integer(kind=intType) :: j
3106 logical :: checkLeft, checkRight, concave
3107 real(kind=realtype),
dimension(3) :: xj, xjm1, xjp1, normj
3108 real(kind=realtype),
dimension(3) :: v
3112 normj = str%norm(:, j)
3114 if (str%isPeriodic)
then
3115 if (j > 1 .and. j < str%nNodes)
then
3116 xjm1 = str%x(:, j - 1)
3117 xjp1 = str%x(:, j + 1)
3118 else if (j == 1)
then
3119 xjm1 = str%x(:, str%nNodes)
3120 xjp1 = str%x(:, j + 1)
3121 else if (j == str%nNodes)
then
3122 xjm1 = str%x(:, j - 1)
3136 if (j == str%nNodes)
then
3137 checkright = .false.
3142 xjm1 = str%x(:, j - 1)
3144 xjp1 = str%x(:, j + 1)
3147 if (checkleft .and. checkright)
then
3153 if (dot_product(v, normj) >
zero)
then
3165 real(kind=realtype),
dimension(3),
intent(in) :: pt, xj, xjm1, xjp1, normj
3166 logical,
intent(in) :: concave, checkleft, checkright
3168 logical :: leftok, rightok
3182 if (.not. (leftok .and. rightok))
then
3186 if (.not. (leftok .or. rightok))
then
3200 real(kind=realtype),
dimension(3),
intent(in) :: pt
3202 integer(kind=intType),
intent(in) :: j
3206 integer(kind=intType) :: i
3207 real(kind=realtype),
dimension(3) :: v, p1, p2, u, norma, normb, x0, norm
3208 real(kind=realtype) :: unrm, x1, x2, x3, x4, y1, y2, y3, y4, idet, px, py
3209 real(kind=realtype) :: u1, u2, v1, v2, w1, w2
3210 real(kind=realtype) :: s1, s2, tmp, line(2), vec(2), tol
3218 norm = str%norm(:, j)
3235 elemloop:
do i = 1, str%nElems
3239 if (str%conn(1, i) == j .or. str%conn(2, i) == j)
then
3244 p1 = str%x(:, str%conn(1, i))
3245 p2 = str%x(:, str%conn(2, i))
3247 norma = str%norm(:, str%conn(1, i))
3248 normb = str%norm(:, str%conn(2, i))
3252 if (dot_product(norma, norm) <
half .or. dot_product(normb, norm) <
half)
then
3256 p1 = p1 - norm * dot_product(p1 - x0, norm)
3257 p2 = p2 - norm * dot_product(p2 - x0, norm)
3260 x3 = dot_product(p1 - x0, u)
3261 y3 = dot_product(p1 - x0, v)
3262 x4 = dot_product(p2 - x0, u)
3263 y4 = dot_product(p2 - x0, v)
3274 s1 = (v2 * w1 - v1 * w2) / (v1 * u2 - v2 * u1)
3275 s2 = (u1 * w2 - u2 * w1) / (u1 * v2 - u2 * v1)
3277 if (s1 > tol .and. s1 <
one - tol .and. s2 > tol .and. s2 <
one - tol)
then
3292 real(kind=realtype),
dimension(3),
intent(in) :: pt1, pt2, norm
3297 integer(kind=intType) :: i
3298 real(kind=realtype),
dimension(3) :: v, p1, p2, u, norma, normb, x0
3299 real(kind=realtype) :: unrm, x1, x2, x3, x4, y1, y2, y3, y4, idet, px, py
3300 real(kind=realtype) :: u1, u2, v1, v2, w1, w2
3301 real(kind=realtype) :: s1, s2, tmp, line(2), vec(2), tol
3325 elemloop:
do i = 1, str%nElems
3328 p1 = str%x(:, str%conn(1, i))
3329 p2 = str%x(:, str%conn(2, i))
3331 norma = str%norm(:, str%conn(1, i))
3332 normb = str%norm(:, str%conn(2, i))
3336 if (dot_product(norma, norm) <
half .or. dot_product(normb, norm) <
half)
then
3340 p1 = p1 - norm * dot_product(p1 - x0, norm)
3341 p2 = p2 - norm * dot_product(p2 - x0, norm)
3344 x3 = dot_product(p1 - x0, u)
3345 y3 = dot_product(p1 - x0, v)
3346 x4 = dot_product(p2 - x0, u)
3347 y4 = dot_product(p2 - x0, v)
3358 s1 = (v2 * w1 - v1 * w2) / (v1 * u2 - v2 * u1)
3359 s2 = (u1 * w2 - u2 * w1) / (u1 * v2 - u2 * v1)
3361 if (s1 > tol .and. s1 <
one - tol .and. s2 > tol .and. s2 <
one - tol)
then
real(kind=realtype), parameter zero
real(kind=realtype), parameter pi
real(kind=realtype), parameter one
real(kind=realtype), parameter half
real(kind=realtype), parameter large
type(kdtree2) function, pointer, public kdtree2_create(input_data, dim, sort, rearrange)
subroutine, public kdtree2_n_nearest(tp, qv, nn, results)
subroutine, public kdtree2_r_nearest(tp, qv, r2, nfound, nalloc, results)
subroutine qsortedgetype(arr, nn)
subroutine createsubstringfromelems(p, s, id)
subroutine crosszip(str1, N1, N2, str2, N3, N4, debugZipper, failed)
subroutine loadzipperdebug(fileName, str)
subroutine writeoversettriangles(string, fileName, startTri, endTri)
subroutine stringmatch(strings, nStrings, debugZipper)
subroutine combinechainbuffers(s)
logical function trioverlap(pt1, pt2, pt3, str, i1, i2)
subroutine makepocketzip(p, strings, nStrings, pocketMaster, debugZipper)
subroutine writeoversetstring(str, strings, n, fileID)
logical function positivetriarea(p1, p2, p3, norm)
subroutine selfzip(s, cutOff, nZipped)
logical function overlappededges(str, j, pt)
logical function overlappededges2(str, pt1, norm, pt2)
recursive subroutine createnodetoelem(string)
subroutine addpotentialtriangle(s, im1, ii, ip1, nodeMap, results, added)
subroutine writezipperdebug(str)
subroutine makecrosszip(p, strings, nStrings, debugZipper)
subroutine performselfzip(master, strings, nStrings, debugZipper)
subroutine dochain(master, iStart, iSub)
subroutine addtri(A, sA, B, sB, C, sC)
subroutine shortenstring(s, nodeMap)
subroutine writeoversetmaster(str, fileID)
subroutine computetrisurfarea(master, area)
subroutine reducegapstring(string)
subroutine pointintriangle(x1, x2, x3, pt, inTri)
subroutine nullifystring(string)
subroutine deallocatestring(string)
subroutine setstringpointers(string)
logical function nodeinfrontofedges(pt, concave, checkLeft, checkRight, xj, xjm1, xjp1, normj)
subroutine getnodeinfo(str, j, checkLeft, checkRight, concave, xj, xjm1, xjp1, normj)
subroutine closestsymmetricnode(s1, s2, i, j)
subroutine createorderedstrings(master, strings, nString)
subroutine cross_prod(a, b, c)
real(kind=realtype) function mynorm2(x)
subroutine pointreduce(pts, N, tol, uniquePts, link, nUnique)
subroutine terminate(routineName, errorMessage)
integer(kind=inttype) function prevnode(s, i)
integer(kind=inttype) function elembetweennodes(str, a, b)
integer(kind=inttype) function elemsforrange(s, N1, N2, pos)
real(kind=realtype) function triarea(pt1, pt2, pt3)
real(kind=realtype) function vecangle(vec1, vec2)
integer(kind=inttype) function simplenextnode(s, i)
integer(kind=inttype) function startnode(s)
subroutine flagnodesused(s, N1, N2, pos)
logical function sameside(p1, p2, a, b)
integer(kind=inttype) function nextnode(str, i, pos)
subroutine tracematch(s, iStart, pos, checkID, iEnd, fullLoop)