I am working with a parallel finite element code that was written by another person, and there are some pieces of code that I can not understand. In particular there is the map creation for the degrees of freedom belonging to each node of the computational mesh. The mesh is made of quadrilateral elements, and each node has nb_dofs degrees of freedom. The elements of the mesh are subdivided into patches and each patch belong to a different processor. Adjacent patches of elements share the same nodes and the same degree of freedom.
The map is created in the following steps.
(1) The functor ``edl'' is created through the call to the constructor:
element_dof_list<mesh_type> edl(mesh);
where mesh is the computational mesh. The body of the constructor is:
element_dof_list(const mesh_type& m):mesh_m(m){},
where m, as I said before, is the mesh used for computation.
(2) The rule according to which the map has to be created is defined through the call:
element_mapping<mesh_type, element_dof_list<mesh_type> > e_dof_map(mesh, edl);
where mesh is the computational mesh and edl is the functor created in (1). The body of the rule constructor is:
element_mapping(const mesh_type& m, const rule_type& r):mesh_m(m),rule_m(r) {}
where, according to the call written above, the member mesh_m is the computational mesh, and the member rule_m is the functor edl.
(3) Finally (but this is the most dificult part), there is the call to the map builder:
dof_map_m = make_map<shared_epetra_map>(e_dof_map);
where shared_epetra_map is a shared Epetra map of the package Trilinos, since the degree of freedom belonging to adjacent patches of elements belonging to different processors are shared. e_dof_map is defined in (2).
The body of the call in (3) is:
template<typename map_type, typename data_type>
inline map_type* make_map(const data_type& g) {
return build_map<map_type, data_type>::do_map( g );
}
where the data_type is element_mapping, and the input argument g is e_dof_map.
This function calls the function
build_map<map_type, data_type>::do_map( g )
according to the data_type passed in input.
In my case the input argument element_mapping causes the call to
template<typename map_type, typename data_type>
struct build_map {
static map_type* do_map(const data_type& g){
return build_map<map_type, typename data_type::result_type>::do_map(g());
}
};
where the operator g()
is called.
The operator g() is simply a nested iteration over all the elements, and all the nodes belonging to the particular element, that extract a std::vector of the degree of freedom for all the mesh (called gid_m). This vector, as I already said, has shared degrees of freedom for elements that are adjacent but belong to different processors.
The do_map(g()) is thus filled with the std::vector gid_m.
(4) Now comes the thing that I can not understand. After the call to
struct build_map {
static map_type* do_map(const data_type& g){
return build_map<map_type, typename data_type::result_type>::do_map(g());
}
};
and the return of g() as std::vector of shared degrees of freedom it is called the function:
template<typename map_type>
struct build_map<map_type, std::valarray<int> > {
static map_type* do_map(const std::valarray<int>& gid) {
return new map_type(-1,gid.size(),&(gid[0]));
}
};
that finally creates the map.
What I do not understand is:
(a) how the code engineering makes the do_map(g())
to call the
do_map(const std::valarray<int>& gid)
(b) how the instruction map_type(-1,gid.size(),&(gid[0]))
can create
the map. I have searched in my code, but I did not find any
instruction that can create a map from the above information
(-1,gid.size(),&(gid[0]))
, is it a standard or may it be a function
of Trilinos?
I hope I was clear enough, but all this calling subsequent structures makes me mad. Is there anybody wishing to help me?
I can not ask the person who wrote the code since he forgot all this chain of calls (some time has passed since he wrote the code, and now he is working in another place on other things).
You are right about the constructor of the shared epetra map, I checked in the epetra package of trilinos and there is a constructor taking as arguments
(-1,gid.size(),&(gid[0])).
But the thing that I can not understand is how from the call to
struct build_map {
static map_type* do_map(const data_type& g){
return build_map<map_type, typename data_type::result_type>::do_map(g());
}
};
where the operatot g() returns a std::vector it is automatically called the function:
template<typename map_type>
struct build_map<map_type, std::valarray<int> > {
static map_type* do_map(const std::valarray<int>& gid) {
return new map_type(-1,gid.size(),&(gid[0]));
}
};