Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
amdis
amdis-core
Commits
7fccb4cf
Commit
7fccb4cf
authored
May 08, 2016
by
Praetorius, Simon
Browse files
kdtree implementation using entity-seeds
parent
ee990734
Changes
1
Hide whitespace changes
Inline
Side-by-side
dune/amdis/test/kdtree.hpp
View file @
7fccb4cf
...
...
@@ -6,27 +6,9 @@
#include
<iostream>
namespace
AMDiS
{
namespace
extensions
{
using
namespace
nanoflann
;
// =====================================================================================
typedef
WorldVector
<
double
>
PointType
;
typedef
boost
::
tuple
<
const
MacroElement
*
,
int
,
unsigned
long
>
DataType
;
typedef
std
::
vector
<
PointType
>
VectorOfPointsType
;
typedef
std
::
vector
<
DataType
>
VectorOfDataType
;
// =====================================================================================
/** A simple vector-of-vectors adaptor for nanoflann, without duplicating the storage.
* The i'th vector represents a point in the state space.
*
* \tparam dim If set to >0, it specifies a compile-time fixed dimensionality for the points in the data set, allowing more compiler optimizations.
* \tparam value_type The type of the point coordinates (typically, double or float).
* \tparam Distance The distance metric to use: nanoflann::metric_L1, nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc.
* \tparam index_type The type for indices in the KD-tree index (typically, size_t of int)
*/
template
<
class
FeSpace
>
namespace
AMDiS
{
template
<
class
FeSpace
>
struct
KDTreeMeshAdaptor
{
using
MeshView
=
typename
FeSpace
::
GridView
;
...
...
@@ -40,17 +22,17 @@ typedef std::vector<DataType> VectorOfDataType;
using
PointType
=
typename
Codim0
::
Geometry
::
GlobalCoordinate
;
using
VectorOfPointsType
=
std
::
vector
<
PointType
>
;
using
DataType
=
std
::
vector
<
Dune
::
FieldVector
<
double
,
1
>
>
;
using
VectorOfDataType
=
std
::
vector
<
std
::
pair
<
std
::
hash
<
DataType
>
,
DataType
>>
>
;
using
DataType
=
typename
MeshView
::
Grid
::
EntitySeed
;
using
VectorOfDataType
=
std
::
vector
<
DataType
>
;
using
Distance
=
nanoflann
::
metric_L2_Simple
;
using
Self
=
KDTreeMeshAdaptor
<
VectorOfPointsType
,
VectorOfDataType
,
ValueType
,
dimensionworld
,
Distance
,
SizeTyp
e
>
;
using
m
etric
_t
=
typename
Distance
::
template
traits
<
ValueType
,
Self
>
::
distance_t
;
using
i
ndex
_t
=
KDTreeSingleIndexAdaptor
<
m
etric
_t
,
Self
,
dimensionworld
,
SizeType
>
;
using
Self
=
KDTreeMeshAdaptor
<
FeSpac
e
>
;
using
M
etric
=
typename
Distance
::
template
traits
<
ValueType
,
Self
>
::
distance_t
;
using
I
ndex
Type
=
nanoflann
::
KDTreeSingleIndexAdaptor
<
M
etric
,
Self
,
dimensionworld
,
SizeType
>
;
public:
unique_ptr
<
i
ndex
_t
>
index
;
//! The kd-tree index for the user to call its methods as usual with any other FLANN index.
unique_ptr
<
I
ndex
Type
>
index
;
//! The kd-tree index for the user to call its methods as usual with any other FLANN index.
FeSpace
const
&
feSpace
;
VectorOfPointsType_
m_points
;
...
...
@@ -63,11 +45,13 @@ typedef std::vector<DataType> VectorOfDataType;
KDTreeMeshAdaptor
(
FeSpace
const
&
feSpace_
,
const
int
leaf_max_size
=
10
)
:
feSpace
(
feSpace_
)
,
localView
(
feSpace
.
localView
())
,
localIndexSet
(
feSpace
.
localIndexSet
())
{
init
();
index
=
make_unique
<
i
ndex
_t
>
(
dimensionworld
,
*
this
/* adaptor */
,
nanoflann
::
KDTreeSingleIndexAdaptorParams
(
leaf_max_size
,
dimensionworld
));
index
=
make_unique
<
I
ndex
Type
>
(
dimensionworld
,
*
this
/* adaptor */
,
nanoflann
::
KDTreeSingleIndexAdaptorParams
(
leaf_max_size
,
dimensionworld
));
index
->
buildIndex
();
}
...
...
@@ -76,21 +60,9 @@ typedef std::vector<DataType> VectorOfDataType;
void
init
()
{
auto
const
&
localView
=
feSpace
.
localView
();
auto
const
&
indexSet
=
feSpace
.
localIndexSet
();
for
(
auto
const
&
element
:
elements
(
feSpace
.
gridView
()))
{
localView
.
bind
(
element
);
localIndexSet
.
bind
(
localView
);
m_points
.
push_back
(
element
.
geometry
().
center
());
auto
const
&
localBasis
=
localView
.
tree
().
finiteElement
().
localBasis
();
std
::
vector
<
SizeType
>
indices
(
localBasis
.
size
());
for
(
size_t
j
=
0
;
j
<
localBasis
.
size
();
++
j
)
indices
[
i
]
=
localIndexSet
.
index
(
j
);
m_data
.
push_back
(
indices
);
m_data
.
push_back
(
element
.
seed
());
}
}
...
...
@@ -99,8 +71,8 @@ typedef std::vector<DataType> VectorOfDataType;
m_points
.
clear
();
m_data
.
clear
();
init
();
index
.
reset
(
new
i
ndex
_t
(
dimensionworld
,
*
this
/* adaptor */
,
nanoflann
::
KDTreeSingleIndexAdaptorParams
(
leaf_max_size
,
dimensionworld
));
index
.
reset
(
new
I
ndex
Type
(
dimensionworld
,
*
this
/* adaptor */
,
nanoflann
::
KDTreeSingleIndexAdaptorParams
(
leaf_max_size
,
dimensionworld
));
index
->
buildIndex
();
}
...
...
@@ -139,20 +111,20 @@ typedef std::vector<DataType> VectorOfDataType;
}
// Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
inline
v
alue
_t
ype
kdtree_distance
(
const
double
*
p1
,
inline
V
alue
T
ype
kdtree_distance
(
const
double
*
p1
,
const
SizeType
idx_p2
,
size_t
size
)
const
{
doubl
e
s
=
0.0
;
ValueTyp
e
s
=
0.0
;
for
(
size_t
i
=
0
;
i
<
size
;
i
++
)
{
const
doubl
e
d
=
p1
[
i
]
-
m_points
[
idx_p2
][
i
];
const
ValueTyp
e
d
=
p1
[
i
]
-
m_points
[
idx_p2
][
i
];
s
+=
d
*
d
;
}
return
s
;
}
// Returns the dim'th component of the idx'th point in the class:
inline
v
alue
_t
ype
kdtree_get_pt
(
const
SizeType
idx
,
size_t
dim
)
const
inline
V
alue
T
ype
kdtree_get_pt
(
const
SizeType
idx
,
size_t
dim
)
const
{
return
m_points
[
idx
][
dim
];
}
...
...
@@ -174,72 +146,75 @@ typedef std::vector<DataType> VectorOfDataType;
* == evalAtPoint_simple
**/
template
<
class
DOFVector
>
typename
DOFVector
::
value_type
evalAtPoint
(
DOFVector
const
&
vec
,
PointType
const
&
x
,
int
strategy
=
0
,
int
nrOfPoints
=
-
1
)
Value_t
<
DOFVector
>
evalAtPoint
(
DOFVector
const
&
vec
,
PointType
const
&
x
)
{
using
T
=
typename
DOFVector
::
value_type
;
T
value
=
0
;
Value_t
<
DOFVector
>
value
=
0
;
std
::
vector
<
SizeType
>
indices
;
if
(
getNearestElement
(
x
,
indices
))
{
// get lambda of point...
return
localEval
(
vec
,
indices
,
lambda
);
auto
const
&
grid
=
vec
.
getFeSpace
().
gridView
().
grid
();
DataType
elementSeed
;
if
(
getNearestElement
(
x
,
elementSeed
))
{
auto
element
=
grid
.
entity
(
elementSeed
);
auto
lambda
=
element
.
geometry
().
local
(
x
);
value
=
localEval
(
vec
,
element
,
lambda
);
}
return
value
;
}
private:
/// evaluate DOFVector at barycentric coordinates \p lambda in element
that
/// is bind to instance in \ref bind().
template
<
class
FE
,
class
ValueType
,
class
Indices
,
class
LocalCoord
>
ValueType
localEval
(
DOFVector
<
FE
,
ValueType
>
const
&
vec
,
Indices
const
&
indices
,
LocalCoord
const
&
lambda
)
/// evaluate DOFVector at barycentric coordinates \p lambda in element
template
<
class
FE
,
class
Value
,
class
Element
,
class
LocalCoords
>
Value
localEval
(
DOFVector
<
FE
,
Value
>
const
&
vec
,
Element
const
&
element
,
LocalCoord
s
const
&
lambda
)
{
auto
const
&
localBasis
=
localView
.
tree
().
finiteElement
().
localBasis
();
localView
.
bind
(
element
);
localIndexSet
.
bind
(
localView
);
// find a way to evaluate basisFcts at lambda!...
auto
const
&
shape
=
shapeValues
[
indices
.
first
];
auto
const
&
localFiniteElem
=
localView
.
tree
().
finiteElement
();
auto
const
&
localBasis
=
localFiniteElem
.
localBasis
();
const
size_t
nBasisFct
=
localFiniteElem
.
size
();
std
::
vector
<
Dune
::
FieldVector
<
double
,
1
>
>
shapeValues
;
localBasis
.
evaluateFunction
(
lambda
,
shapeValues
);
assert
(
shape
.
size
()
==
indices
.
size
()
)
;
ValueType
data
=
0
;
for
(
size_t
j
=
0
;
j
<
shape
.
size
();
++
j
)
data
+=
vec
[
indices
.
second
[
j
]]
*
shape
[
j
];
Value
data
=
0
;
for
(
size_t
j
=
0
;
j
<
nBasisFct
;
++
j
)
{
auto
const
global_idx
=
localIndexSet
.
index
(
j
)
;
data
+=
vector
[
global_idx
]
*
shapeValues
[
j
];
}
return
data
;
}
template
<
class
Indices
>
bool
getNearestElement
(
PointType
&
x
,
Indices
&
indices
)
bool
getNearestElement
(
PointType
const
&
x
,
DataType
&
elementSeed
)
{
const
size_t
n
np
=
1
;
std
::
vector
<
DegreeOfFreedom
>
ret_indexes
(
n
np
);
std
::
vector
<
double
>
out_dists_sqr
(
n
np
);
nanoflann
::
KNNResultSet
<
double
,
DegreeOfFreedom
>
resultSet
(
n
np
);
const
size_t
n
rOfPoints
=
1
;
std
::
vector
<
DegreeOfFreedom
>
ret_indexes
(
n
rOfPoints
);
std
::
vector
<
double
>
out_dists_sqr
(
n
rOfPoints
);
nanoflann
::
KNNResultSet
<
double
,
DegreeOfFreedom
>
resultSet
(
n
rOfPoints
);
resultSet
.
init
(
&
ret_indexes
[
0
],
&
out_dists_sqr
[
0
]);
index
->
findNeighbors
(
resultSet
,
x
.
begin
(),
nanoflann
::
SearchParams
());
indices
=
m_data
[
ret_indexes
[
0
]];
elementSeed
=
m_data
[
ret_indexes
[
0
]];
return
true
;
}
private:
typename
FeSpace
::
LocalView
localView
;
typename
FeSpace
::
LocalIndexSet
localIndexSet
;
};
// end of KDTreeMeshAdaptor
template
<
class
FeSpace
>
auto
provideKDTree
(
FeSpace
const
&
gridView
)
auto
provideKDTree
(
FeSpace
const
&
feSpace
)
{
using
GridView
=
typename
FeSpace
::
GridView
;
static
constexpr
int
dow
=
GridView
::
dimensionworld
;
using
KD_Tree
=
KDTreeMeshAdaptor
<
FeSpace
,
VectorOfPointsType
,
VectorOfDataType
,
double
,
dow
>
;
using
KD_Tree
=
KDTreeMeshAdaptor
<
FeSpace
>
;
return
make_unique
<
KD_Tree
_M
>
(
dow
,
gridView
);
return
make_unique
<
KD_Tree
>
(
feSpace
);
}
}
}
}
// end namespace AMDiS
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment