Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F91388276
element_synchronizer.cc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Nov 10, 15:18
Size
9 KB
Mime Type
text/x-c
Expires
Tue, Nov 12, 15:18 (2 d)
Engine
blob
Format
Raw Data
Handle
22224478
Attached To
rAKA akantu
element_synchronizer.cc
View Options
/**
* Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
#include "element_synchronizer.hh"
#include "aka_common.hh"
#include "mesh.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <iostream>
#include <map>
/* -------------------------------------------------------------------------- */
namespace
akantu
{
#if defined(AKANTU_MODULE)
#define AKANTU_MODULE_SAVE_ AKANTU_MODULE
#undef AKANTU_MODULE
#endif
#define AKANTU_MODULE element_synchronizer
/* -------------------------------------------------------------------------- */
ElementSynchronizer
::
ElementSynchronizer
(
Mesh
&
mesh
,
const
ID
&
id
,
bool
register_to_event_manager
,
EventHandlerPriority
event_priority
)
:
SynchronizerImpl
<
Element
>
(
mesh
.
getCommunicator
(),
id
),
mesh
(
mesh
),
element_to_prank
(
"element_to_prank"
,
id
)
{
AKANTU_DEBUG_IN
();
if
(
register_to_event_manager
)
{
this
->
mesh
.
registerEventHandler
(
*
this
,
event_priority
);
}
AKANTU_DEBUG_OUT
();
}
/* -------------------------------------------------------------------------- */
ElementSynchronizer
::
ElementSynchronizer
(
const
ElementSynchronizer
&
other
,
const
ID
&
id
,
bool
register_to_event_manager
,
EventHandlerPriority
event_priority
)
:
SynchronizerImpl
<
Element
>
(
other
,
id
),
mesh
(
other
.
mesh
),
element_to_prank
(
"element_to_prank"
,
id
)
{
AKANTU_DEBUG_IN
();
element_to_prank
.
copy
(
other
.
element_to_prank
);
if
(
register_to_event_manager
)
{
this
->
mesh
.
registerEventHandler
(
*
this
,
event_priority
);
}
AKANTU_DEBUG_OUT
();
}
/* -------------------------------------------------------------------------- */
ElementSynchronizer
::~
ElementSynchronizer
()
=
default
;
/* -------------------------------------------------------------------------- */
void
ElementSynchronizer
::
substituteElements
(
const
std
::
map
<
Element
,
Element
>
&
old_to_new_elements
)
{
auto
found_element_end
=
old_to_new_elements
.
end
();
// substitute old elements with new ones
for
(
auto
&&
sr
:
iterate_send_recv
)
{
for
(
auto
&&
scheme_pair
:
communications
.
iterateSchemes
(
sr
))
{
auto
&
list
=
scheme_pair
.
second
;
for
(
auto
&
el
:
list
)
{
auto
found_element_it
=
old_to_new_elements
.
find
(
el
);
if
(
found_element_it
!=
found_element_end
)
{
el
=
found_element_it
->
second
;
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void
ElementSynchronizer
::
onElementsChanged
(
const
Array
<
Element
>
&
old_elements_list
,
const
Array
<
Element
>
&
new_elements_list
,
const
ElementTypeMapArray
<
Idx
>
&
,
const
ChangedElementsEvent
&
)
{
// create a map to link old elements to new ones
std
::
map
<
Element
,
Element
>
old_to_new_elements
;
for
(
Int
el
=
0
;
el
<
old_elements_list
.
size
();
++
el
)
{
AKANTU_DEBUG_ASSERT
(
old_to_new_elements
.
find
(
old_elements_list
(
el
))
==
old_to_new_elements
.
end
(),
"The same element cannot appear twice in the list"
);
old_to_new_elements
[
old_elements_list
(
el
)]
=
new_elements_list
(
el
);
}
substituteElements
(
old_to_new_elements
);
communications
.
invalidateSizes
();
}
/* -------------------------------------------------------------------------- */
void
ElementSynchronizer
::
onElementsRemoved
(
const
Array
<
Element
>
&
element_to_remove
,
const
ElementTypeMapArray
<
Idx
>
&
new_numbering
,
const
RemovedElementsEvent
&
)
{
AKANTU_DEBUG_IN
();
this
->
filterScheme
([
&
](
auto
&&
element
)
{
return
std
::
find
(
element_to_remove
.
begin
(),
element_to_remove
.
end
(),
element
)
==
element_to_remove
.
end
();
});
this
->
renumberElements
(
new_numbering
);
communications
.
invalidateSizes
();
AKANTU_DEBUG_OUT
();
}
/* -------------------------------------------------------------------------- */
void
ElementSynchronizer
::
buildElementToPrank
()
{
AKANTU_DEBUG_IN
();
Int
spatial_dimension
=
mesh
.
getSpatialDimension
();
element_to_prank
.
initialize
(
mesh
,
_spatial_dimension
=
spatial_dimension
,
_element_kind
=
_ek_not_defined
,
_with_nb_element
=
true
,
_default_value
=
rank
);
/// assign prank to all ghost elements
for
(
auto
&&
scheme
:
communications
.
iterateSchemes
(
_recv
))
{
auto
&
recv
=
scheme
.
second
;
auto
proc
=
scheme
.
first
;
for
(
auto
&
element
:
recv
)
{
element_to_prank
(
element
)
=
proc
;
}
}
AKANTU_DEBUG_OUT
();
}
/* -------------------------------------------------------------------------- */
Int
ElementSynchronizer
::
getRank
(
const
Element
&
element
)
const
{
if
(
not
element_to_prank
.
exists
(
element
.
type
,
element
.
ghost_type
))
{
// Nicolas: Ok This is nasty I know....
const_cast
<
ElementSynchronizer
*>
(
this
)
->
buildElementToPrank
();
}
return
element_to_prank
(
element
);
}
/* -------------------------------------------------------------------------- */
void
ElementSynchronizer
::
renumberElements
(
const
ElementTypeMapArray
<
Idx
>
&
new_numbering
)
{
for
(
auto
&&
sr
:
iterate_send_recv
)
{
for
(
auto
&&
scheme_pair
:
communications
.
iterateSchemes
(
sr
))
{
auto
&
list
=
scheme_pair
.
second
;
for
(
auto
&&
el
:
list
)
{
if
(
new_numbering
.
exists
(
el
.
type
,
el
.
ghost_type
))
{
el
.
element
=
new_numbering
(
el
);
}
}
}
}
}
/* -------------------------------------------------------------------------- */
Int
ElementSynchronizer
::
sanityCheckDataSize
(
const
Array
<
Element
>
&
elements
,
const
SynchronizationTag
&
tag
,
bool
from_comm_desc
)
const
{
Int
size
=
SynchronizerImpl
<
Element
>::
sanityCheckDataSize
(
elements
,
tag
,
from_comm_desc
);
// global connectivities;
size
+=
mesh
.
getNbNodesPerElementList
(
elements
)
*
sizeof
(
Idx
);
// barycenters
size
+=
(
elements
.
size
()
*
mesh
.
getSpatialDimension
()
*
sizeof
(
Real
));
return
size
;
}
/* -------------------------------------------------------------------------- */
void
ElementSynchronizer
::
packSanityCheckData
(
CommunicationBuffer
&
buffer
,
const
Array
<
Element
>
&
elements
,
const
SynchronizationTag
&
/*tag*/
)
const
{
for
(
auto
&&
element
:
elements
)
{
Vector
<
Real
>
barycenter
(
mesh
.
getSpatialDimension
());
mesh
.
getBarycenter
(
element
,
barycenter
);
buffer
<<
barycenter
;
const
auto
&
conns
=
mesh
.
getConnectivity
(
element
.
type
,
element
.
ghost_type
);
for
(
auto
n
:
arange
(
conns
.
getNbComponent
()))
{
buffer
<<
mesh
.
getNodeGlobalId
(
conns
(
element
.
element
,
n
));
}
}
}
/* -------------------------------------------------------------------------- */
void
ElementSynchronizer
::
unpackSanityCheckData
(
CommunicationBuffer
&
buffer
,
const
Array
<
Element
>
&
elements
,
const
SynchronizationTag
&
tag
,
Int
proc
,
Int
rank
)
const
{
auto
spatial_dimension
=
mesh
.
getSpatialDimension
();
std
::
set
<
SynchronizationTag
>
skip_conn_tags
{
SynchronizationTag
::
_smmc_facets_conn
,
SynchronizationTag
::
_giu_global_conn
};
bool
is_skip_tag_conn
=
skip_conn_tags
.
find
(
tag
)
!=
skip_conn_tags
.
end
();
for
(
auto
&&
element
:
elements
)
{
Vector
<
Real
>
barycenter_loc
(
spatial_dimension
);
mesh
.
getBarycenter
(
element
,
barycenter_loc
);
Vector
<
Real
>
barycenter
(
spatial_dimension
);
buffer
>>
barycenter
;
auto
dist
=
barycenter_loc
.
distance
(
barycenter
);
if
(
not
Math
::
are_float_equal
(
dist
,
0.
))
{
AKANTU_EXCEPTION
(
"Unpacking an unknown value for the element "
<<
element
<<
"(barycenter "
<<
barycenter_loc
<<
" != buffer "
<<
barycenter
<<
") ["
<<
dist
<<
"] - tag: "
<<
tag
<<
" comm from "
<<
proc
<<
" to "
<<
rank
);
}
const
auto
&
conns
=
mesh
.
getConnectivity
(
element
.
type
,
element
.
ghost_type
);
Vector
<
Idx
>
global_conn
(
conns
.
getNbComponent
());
Vector
<
Idx
>
local_global_conn
(
conns
.
getNbComponent
());
auto
is_same
=
true
;
for
(
auto
n
:
arange
(
global_conn
.
size
()))
{
buffer
>>
global_conn
(
n
);
auto
node
=
conns
(
element
.
element
,
n
);
local_global_conn
(
n
)
=
mesh
.
getNodeGlobalId
(
node
);
is_same
&=
is_skip_tag_conn
or
mesh
.
isPureGhostNode
(
node
)
or
(
local_global_conn
(
n
)
==
global_conn
(
n
));
}
if
(
not
is_same
)
{
AKANTU_DEBUG_WARNING
(
"The connectivity of the element "
<<
element
<<
" "
<<
local_global_conn
<<
" does not match the connectivity of the equivalent "
"element on proc "
<<
proc
<<
" "
<<
global_conn
<<
" in communication with tag "
<<
tag
);
}
}
}
/* -------------------------------------------------------------------------- */
}
// namespace akantu
#if defined(AKANTU_MODULE_SAVE_)
#undef AKANTU_MODULE
#define AKANTU_MODULE AKANTU_MODULE_SAVE_
#undef AKANTU_MODULE_SAVE_
#endif
Event Timeline
Log In to Comment