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
iwr
amdis
Commits
8f6cf14b
Commit
8f6cf14b
authored
Nov 10, 2012
by
Thomas Witkowski
Browse files
Fixed fixing 3d mesh refinement for very complicated macro mesh partitionings.
parent
13a09f5b
Changes
3
Hide whitespace changes
Inline
Side-by-side
AMDiS/src/RefinementManager3d.cc
View file @
8f6cf14b
...
...
@@ -683,8 +683,7 @@ namespace AMDiS {
}
for
(
int
edgeIndex
=
0
;
edgeIndex
<
static_cast
<
unsigned
int
>
(
refineEdges
.
size
());
edgeIndex
++
)
{
edgeIndex
<
static_cast
<
unsigned
int
>
(
refineEdges
.
size
());
edgeIndex
++
)
{
MSG
(
" MAKE -> %d
\n
"
,
edgeIndex
);
Element
*
otherEl
=
refineEdges
[
edgeIndex
].
first
;
...
...
AMDiS/src/parallel/MeshDistributor.cc
View file @
8f6cf14b
...
...
@@ -209,7 +209,7 @@ namespace AMDiS {
return
;
}
// Create a very first pariitioning of the mesh.
createInitialPartitioning
();
...
...
@@ -291,11 +291,10 @@ namespace AMDiS {
updateLocalGlobalNumbering
();
// === In 3D we have to make some test, if the resulting mesh is valid. ===
// === If it is not valid, there is no possiblity yet to fix this ===
// === problem, just exit with an error message. ===
check3dValidMesh();
// === In 3D we have to fix the mesh to allow local refinements. ===
fix3dMeshRefinement
();
// === If in debug mode, make some tests. ===
...
...
@@ -658,13 +657,17 @@ namespace AMDiS {
}
void MeshDistributor::
check3dValidMesh
()
void
MeshDistributor
::
fix3dMeshRefinement
()
{
FUNCNAME("MeshDistributor::
check3dValidMesh
()");
FUNCNAME
(
"MeshDistributor::
fix3dMeshRefinement
()"
);
if
(
mesh
->
getDim
()
!=
3
)
return
;
MPI
::
COMM_WORLD
.
Barrier
();
double
first
=
MPI
::
Wtime
();
// === Create set of all edges and all macro element indices in rank's ===
// === subdomain. ===
...
...
@@ -674,7 +677,7 @@ namespace AMDiS {
TraverseStack
stack
;
ElInfo
*
elInfo
=
stack
.
traverseFirst
(
mesh
,
0
,
Mesh
::
CALL_EL_LEVEL
);
while
(
elInfo
)
{
for (int i = 0; i <
6
; i++) {
for
(
int
i
=
0
;
i
<
mesh
->
getGeo
(
EDGE
)
;
i
++
)
{
ElementObjectData
elData
(
elInfo
->
getElement
()
->
getIndex
(),
i
);
DofEdge
e
=
elObjDb
.
getEdgeLocalMap
(
elData
);
allEdges
.
insert
(
e
);
...
...
@@ -686,11 +689,10 @@ namespace AMDiS {
}
// === Reset fixed
refinement
edges and
assume the mesh is valid. Search
===
// ===
for the opposite.
===
// === Reset fixed edges
,
and
start new search for edges that must
===
// ===
be fixed.
===
FixRefinementPatch
::
connectedEdges
.
clear
();
bool valid3dMesh = true;
// Traverse all edges
for
(
std
::
set
<
DofEdge
>::
iterator
it
=
allEdges
.
begin
();
it
!=
allEdges
.
end
();
++
it
)
{
...
...
@@ -702,91 +704,111 @@ namespace AMDiS {
// We have now to check, if the current edge connects two macro elements,
// which are otherwise not connected. The basic idea to check this is very
// simple: We take the first macro element in rank's subdomain that contain
// this edge and add it to the set variable "el0". All other macro elements
// which share this edge are added to "el1".
// which are otherwise not connected.
std::set<int> el0, el1;
// All elements on this edge.
std
::
set
<
int
>
allEls
;
// Maps from each element index to the local edge index of the common edge.
map
<
int
,
int
>
edgeNoInEl
;
for
(
unsigned
int
i
=
0
;
i
<
edgeEls
.
size
();
i
++
)
{
if
(
rankMacroEls
.
count
(
edgeEls
[
i
].
elIndex
))
{
if (el0.empty())
el0.insert(edgeEls[i].elIndex);
else
el1.insert(edgeEls[i].elIndex);
allEls
.
insert
(
edgeEls
[
i
].
elIndex
);
edgeNoInEl
[
edgeEls
[
i
].
elIndex
]
=
edgeEls
[
i
].
ithObject
;
}
}
TEST_EXIT_DBG(!
el0
.empty())("Should not happen!\n");
TEST_EXIT_DBG
(
!
allEls
.
empty
())(
"Should not happen!
\n
"
);
// If el1 is empty, there is only on macro element in the mesh which
// contains this edge. Hence, we can continue with checking another edge.
if (el1.empty())
// If there is only one element in rank on this edge, there is nothing
// to do.
if
(
allEls
.
size
()
==
1
)
continue
;
bool found = false;
do {
found = false;
for (std::set<int>::iterator elIt = el0.begin(); elIt != el0.end(); ++elIt) {
for (int i = 0; i < 4; i++) {
int neighEl = macroElementNeighbours[*elIt][i];
if (neighEl != -1 && el1.count(neighEl)) {
el0.insert(neighEl);
el1.erase(neighEl);
found = true;
}
}
if (found)
break;
}
} while (found);
// Create a set of element index sets. All element within one set are
// neighbours of each other, but can not reach any other element of the
// other index sets by neighbourhood relations.
vector
<
std
::
set
<
int
>
>
disconnectedEls
;
helpToFix
(
allEls
,
edgeNoInEl
,
disconnectedEls
);
if (!el1.empty()) {
valid3dMesh = false;
MSG_DBG("Unvalid 3D mesh with %d (%d - %d) elements on this edge!\n",
edgeEls.size(), el0.size(), el1.size());
for (std::set<int>::iterator elIt0 = el0.begin(); elIt0 != el0.end(); ++elIt0) {
for (std::set<int>::iterator elIt1 = el1.begin(); elIt1 != el1.end(); ++elIt1) {
pair<Element*, int> edge0 =
make_pair(elObjDb.getElementPtr(*elIt0), edgeNoInEl[*elIt0]);
// Fix the edges
for
(
int
dc0
=
0
;
dc0
<
static_cast
<
int
>
(
disconnectedEls
.
size
());
dc0
++
)
{
for
(
int
dc1
=
0
;
dc1
<
static_cast
<
int
>
(
disconnectedEls
.
size
());
dc1
++
)
{
if
(
dc0
==
dc1
)
continue
;
int
elIdx
=
*
(
disconnectedEls
[
dc1
].
begin
());
pair
<
Element
*
,
int
>
edge0
=
make_pair
(
elObjDb
.
getElementPtr
(
elIdx
),
edgeNoInEl
[
elIdx
]);
for
(
std
::
set
<
int
>::
iterator
elIt
=
disconnectedEls
[
dc0
].
begin
();
elIt
!=
disconnectedEls
[
dc0
].
end
();
++
elIt
)
{
pair
<
Element
*
,
int
>
edge1
=
make_pair(elObjDb.getElementPtr(*elIt
1
), edgeNoInEl[*elIt
1
]);
make_pair
(
elObjDb
.
getElementPtr
(
*
elIt
),
edgeNoInEl
[
*
elIt
]);
#if (DEBUG != 0)
DofEdge
dofEdge0
=
edge0
.
first
->
getEdge
(
edge0
.
second
);
DofEdge
dofEdge1
=
edge1
.
first
->
getEdge
(
edge1
.
second
);
WorldVector
<
double
>
c0
,
c1
;
mesh
->
getDofIndexCoords
(
dofEdge0
.
first
,
feSpaces
[
0
],
c0
);
mesh
->
getDofIndexCoords
(
dofEdge0
.
second
,
feSpaces
[
0
],
c1
);
// MSG("FOUND EDGE %d/%d <-> %d/%d\n",
// edge0.first->getIndex(), edge0.second,
// edge1.first->getIndex(), edge1.second);
// MSG("FOUND EDGE: %d %d with coords %f %f %f %f %f %f\n",
// dofEdge0.first, dofEdge0.second,
// c0[0], c0[1], c0[2],
// c1[0], c1[1], c1[2]);
TEST_EXIT_DBG
(
dofEdge0
==
dofEdge1
)(
"Should noth happen!
\n
"
);
#endif
MSG("FOUND EDGE %d/%d <-> %d/%d\n",
edge0.first->getIndex(), edge0.second,
edge1.first->getIndex(), edge1.second);
FixRefinementPatch
::
connectedEdges
.
push_back
(
make_pair
(
edge1
,
edge0
));
}
}
}
}
MSG("FOUND EDGE: %d %d with coords %f %f %f %f %f %f\n",
dofEdge0.first, dofEdge0.second,
c0[0], c0[1], c0[2],
c1[0], c1[1], c1[2]);
#endif
TEST_EXIT_DBG(dofEdge0 == dofEdge1)("Should noth happen!\n");
MPI
::
COMM_WORLD
.
Barrier
();
MSG
(
"Fix 3D mesh refinement needed %.5f seconds
\n
"
,
MPI
::
Wtime
()
-
first
);
}
FixRefinementPatch::connectedEdges.push_back(make_pair(edge0, edge1));
FixRefinementPatch::connectedEdges.push_back(make_pair(edge1, edge0));
void
MeshDistributor
::
helpToFix
(
std
::
set
<
int
>
&
elems
,
map
<
int
,
int
>
&
edgeNoInEl
,
vector
<
std
::
set
<
int
>
>
&
disconnectedEls
)
{
std
::
set
<
int
>
firstElem
;
firstElem
.
insert
(
*
(
elems
.
begin
()));
std
::
set
<
int
>
otherElems
(
++
(
elems
.
begin
()),
elems
.
end
());
bool
found
=
false
;
do
{
found
=
false
;
for
(
std
::
set
<
int
>::
iterator
elIt
=
firstElem
.
begin
();
elIt
!=
firstElem
.
end
();
++
elIt
)
{
for
(
int
i
=
0
;
i
<
mesh
->
getGeo
(
NEIGH
);
i
++
)
{
int
neighEl
=
macroElementNeighbours
[
*
elIt
][
i
];
if
(
neighEl
!=
-
1
&&
otherElems
.
count
(
neighEl
))
{
firstElem
.
insert
(
neighEl
);
otherElems
.
erase
(
neighEl
);
found
=
true
;
}
}
if
(
found
)
break
;
}
}
}
while
(
found
);
MSG_DBG("Mesh is 3d valid mesh: %d\n", valid3dMesh);
disconnectedEls
.
push_back
(
firstElem
);
if
(
otherElems
.
size
())
helpToFix
(
otherElems
,
edgeNoInEl
,
disconnectedEls
);
}
...
...
@@ -1614,7 +1636,7 @@ namespace AMDiS {
#endif
// In 3D we have to make some test, if the resulting mesh is valid.
check3dValidMesh
();
fix3dMeshRefinement
();
MPI
::
COMM_WORLD
.
Barrier
();
...
...
AMDiS/src/parallel/MeshDistributor.h
View file @
8f6cf14b
...
...
@@ -282,7 +282,23 @@ namespace AMDiS {
/// only on one edge are not neighours by definition. This functions checks
/// for this situation and fix the problem. For this, the mesh is search for
/// all edges connecting two elements that are otherwise not connected.
void
check3dValidMesh
();
void
fix3dMeshRefinement
();
/** \brief Is used only within \ref fix3dMeshRefinement.
*
* \param[in] elems Set of macro element indices.
* \param[in] edgeNoInEl Maps from each element index in elems to a
* local edge number.
* \param[out] disconnectedEls On output, this vector contains sets of
* element indices. The union is equal to elems.
* Each set contains all element indices, which
* are reachable among each other by neighbour
* relations. Elements within two different sets
* cannot be reached via neigbourhood relation.
*/
void
helpToFix
(
std
::
set
<
int
>
&
elems
,
map
<
int
,
int
>
&
edgeNoInEl
,
vector
<
std
::
set
<
int
>
>
&
disconnectedEls
);
void
setBoundaryDofRequirement
(
Flag
flag
)
{
...
...
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