Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
tnl-dev
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Model registry
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
TNL
tnl-dev
Commits
b51661eb
There was an error fetching the commit references. Please try again later.
Commit
b51661eb
authored
3 years ago
by
Jakub Klinkovský
Browse files
Options
Downloads
Patches
Plain Diff
Added function to deduplicate points in MeshBuilder
parent
b35cdc40
No related branches found
No related tags found
1 merge request
!117
Mesh followup
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/TNL/Meshes/MeshBuilder.h
+126
-5
126 additions, 5 deletions
src/TNL/Meshes/MeshBuilder.h
with
126 additions
and
5 deletions
src/TNL/Meshes/MeshBuilder.h
+
126
−
5
View file @
b51661eb
...
...
@@ -16,6 +16,9 @@
#pragma once
#include
<numeric>
// std::iota
#include
<vector>
#include
<TNL/Containers/Vector.h>
#include
<TNL/Meshes/Topologies/Polyhedron.h>
...
...
@@ -31,14 +34,16 @@ public:
using
GlobalIndexType
=
typename
MeshTraitsType
::
GlobalIndexType
;
using
LocalIndexType
=
typename
MeshTraitsType
::
LocalIndexType
;
using
PointType
=
typename
MeshTraitsType
::
PointType
;
using
PointArrayType
=
typename
MeshTraitsType
::
PointArrayType
;
using
BoolVector
=
Containers
::
Vector
<
bool
,
Devices
::
Host
,
GlobalIndexType
>
;
using
CellTopology
=
typename
MeshTraitsType
::
CellTopology
;
using
CellSeedMatrixType
=
typename
MeshTraitsType
::
CellSeedMatrixType
;
using
CellSeedType
=
typename
CellSeedMatrixType
::
EntitySeedMatrixSeed
;
using
FaceSeedMatrixType
=
typename
MeshTraitsType
::
FaceSeedMatrixType
;
using
FaceSeedType
=
typename
FaceSeedMatrixType
::
EntitySeedMatrixSeed
;
using
NeighborCountsArray
=
typename
MeshTraitsType
::
NeighborCountsArray
;
void
setEntitiesCount
(
const
GlobalIndexType
&
points
,
void
setEntitiesCount
(
const
GlobalIndexType
&
points
,
const
GlobalIndexType
&
cells
=
0
,
const
GlobalIndexType
&
faces
=
0
)
{
...
...
@@ -109,20 +114,136 @@ public:
return
this
->
cellSeeds
.
getSeed
(
index
);
}
void
deduplicatePoints
(
const
double
numericalThreshold
=
1e-9
)
{
// prepare vector with an identity permutationutation
std
::
vector
<
GlobalIndexType
>
permutation
(
points
.
getSize
()
);
std
::
iota
(
permutation
.
begin
(),
permutation
.
end
(),
(
GlobalIndexType
)
0
);
// workaround for lexicographical sorting
// FIXME: https://mmg-gitlab.fjfi.cvut.cz/gitlab/tnl/tnl-dev/-/issues/79
auto
lexless
=
[
numericalThreshold
,
this
]
(
const
GlobalIndexType
&
a
,
const
GlobalIndexType
&
b
)
->
bool
{
const
PointType
&
left
=
this
->
points
[
a
];
const
PointType
&
right
=
this
->
points
[
b
];
for
(
LocalIndexType
i
=
0
;
i
<
PointType
::
getSize
();
i
++
)
if
(
TNL
::
abs
(
left
[
i
]
-
right
[
i
]
)
>
numericalThreshold
)
return
left
[
i
]
<
right
[
i
];
return
false
;
};
// sort points in lexicographical order
std
::
stable_sort
(
permutation
.
begin
(),
permutation
.
end
(),
lexless
);
// old -> new index mapping for points
std
::
vector
<
GlobalIndexType
>
points_perm_to_new
(
points
.
getSize
()
);
// find duplicate points
GlobalIndexType
uniquePointsCount
=
0
;
// first index is unique
points_perm_to_new
[
permutation
[
0
]
]
=
uniquePointsCount
++
;
for
(
GlobalIndexType
i
=
1
;
i
<
points
.
getSize
();
i
++
)
{
const
PointType
&
curr
=
points
[
permutation
[
i
]
];
const
PointType
&
prev
=
points
[
permutation
[
i
-
1
]
];
if
(
maxNorm
(
curr
-
prev
)
>
numericalThreshold
)
// unique point
points_perm_to_new
[
permutation
[
i
]
]
=
uniquePointsCount
++
;
else
// duplicate point - use previous index
points_perm_to_new
[
permutation
[
i
]
]
=
uniquePointsCount
-
1
;
}
// if all points are unique, we are done
if
(
uniquePointsCount
==
points
.
getSize
()
)
return
;
std
::
cout
<<
"Found "
<<
points
.
getSize
()
-
uniquePointsCount
<<
" duplicate points (total "
<<
points
.
getSize
()
<<
", unique "
<<
uniquePointsCount
<<
")"
<<
std
::
endl
;
// copy this->points and this->pointsSet, drop duplicate points
// (trying to do this in-place is not worth it, since even Array::reallocate
// needs to allocate a temporary array and copy the elements)
PointArrayType
newPoints
(
uniquePointsCount
);
BoolVector
newPointsSet
(
uniquePointsCount
);
std
::
vector
<
GlobalIndexType
>
points_old_to_new
(
points
.
getSize
()
);
// TODO: this can almost be parallelized, except we have multiple writes for the duplicate points
for
(
std
::
size_t
i
=
0
;
i
<
points_perm_to_new
.
size
();
i
++
)
{
const
GlobalIndexType
oldIndex
=
permutation
[
i
];
const
GlobalIndexType
newIndex
=
points_perm_to_new
[
oldIndex
];
newPoints
[
newIndex
]
=
points
[
oldIndex
];
newPointsSet
[
newIndex
]
=
pointsSet
[
oldIndex
];
points_old_to_new
[
oldIndex
]
=
newIndex
;
}
points
=
std
::
move
(
newPoints
);
pointsSet
=
std
::
move
(
newPointsSet
);
// reset permutation and points_perm_to_new - we need just points_old_to_new further on
permutation
.
clear
();
permutation
.
shrink_to_fit
();
points_perm_to_new
.
clear
();
points_perm_to_new
.
shrink_to_fit
();
auto
remap_matrix
=
[
uniquePointsCount
,
&
points_old_to_new
]
(
auto
&
seeds
)
{
// TODO: optimize out useless copy and counting corner counts - it would be sufficient to just remap column indices and then shrink the columns count
std
::
remove_reference_t
<
decltype
(
seeds
)
>
newSeeds
;
newSeeds
.
setDimensions
(
seeds
.
getMatrix
().
getRows
(),
uniquePointsCount
);
newSeeds
.
setEntityCornersCounts
(
seeds
.
getEntityCornerCounts
()
);
// TODO: parallelize (we have the IndexPermutationApplier)
for
(
GlobalIndexType
i
=
0
;
i
<
newSeeds
.
getEntitiesCount
();
i
++
)
{
const
auto
oldSeed
=
seeds
.
getSeed
(
i
);
auto
seed
=
newSeeds
.
getSeed
(
i
);
for
(
LocalIndexType
j
=
0
;
j
<
seed
.
getCornersCount
();
j
++
)
{
const
GlobalIndexType
newIndex
=
points_old_to_new
[
oldSeed
.
getCornerId
(
j
)
];
seed
.
setCornerId
(
j
,
newIndex
);
}
}
seeds
=
std
::
move
(
newSeeds
);
};
// remap points in this->faceSeeds or this->cellSeeds
if
(
faceSeeds
.
empty
()
)
remap_matrix
(
cellSeeds
);
else
remap_matrix
(
faceSeeds
);
}
bool
build
(
MeshType
&
mesh
)
{
if
(
!
this
->
validate
()
)
return
false
;
pointsSet
.
reset
();
mesh
.
init
(
this
->
points
,
this
->
faceSeeds
,
this
->
cellSeeds
);
return
true
;
}
private
:
using
PointArrayType
=
typename
MeshTraitsType
::
PointArrayType
;
using
BoolVector
=
Containers
::
Vector
<
bool
,
Devices
::
Host
,
GlobalIndexType
>
;
bool
validate
()
const
{
// verify that matrix dimensions are consistent with points
if
(
faceSeeds
.
empty
()
)
{
// no face seeds - cell seeds refer to points
if
(
cellSeeds
.
getMatrix
().
getColumns
()
!=
points
.
getSize
()
)
{
std
::
cerr
<<
"Mesh builder error: Inconsistent size of the cellSeeds matrix (it has "
<<
cellSeeds
.
getMatrix
().
getColumns
()
<<
" columns, but there are "
<<
points
.
getSize
()
<<
" points)."
<<
std
::
endl
;
return
false
;
}
}
else
{
// cell seeds refer to faces and face seeds refer to points
if
(
cellSeeds
.
getMatrix
().
getColumns
()
!=
faceSeeds
.
getMatrix
().
getRows
()
)
{
std
::
cerr
<<
"Mesh builder error: Inconsistent size of the cellSeeds matrix (it has "
<<
cellSeeds
.
getMatrix
().
getColumns
()
<<
" columns, but there are "
<<
faceSeeds
.
getMatrix
().
getRows
()
<<
" faces)."
<<
std
::
endl
;
return
false
;
}
if
(
faceSeeds
.
getMatrix
().
getColumns
()
!=
points
.
getSize
()
)
{
std
::
cerr
<<
"Mesh builder error: Inconsistent size of the faceSeeds matrix (it has "
<<
faceSeeds
.
getMatrix
().
getColumns
()
<<
" columns, but there are "
<<
points
.
getSize
()
<<
" points)."
<<
std
::
endl
;
return
false
;
}
}
if
(
min
(
pointsSet
)
!=
true
)
{
std
::
cerr
<<
"Mesh builder error: Not all points were set."
<<
std
::
endl
;
return
false
;
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment