Commit 7022e0cb authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

#1443 WIP: the test still fails due to a chicken and egg problem: I need to...

#1443 WIP: the test still fails due to a chicken and egg problem: I need to isolate only Dofs related to a numbering subset to renumber them, but to know their NumberingSubset I need first their index... To break that I will change the weak dependancy: currently a Dof has a weak pointer to the NodeBearer, shortcircuiting the Node in the process... too bad the Node is the one to get the intel I need! I will therefore make the weak pointer toward the node, which itself will point toward the NodeBearer.
parent c6825c26
......@@ -44,6 +44,7 @@ namespace MoReFEM
const auto& dof_ptr = pair.first;
assert(!(!dof_ptr));
dof_list_.push_back(dof_ptr);
std::cout << "======================= DofStorage" << std::endl;
program_wise_dof_index_list_.push_back(static_cast<PetscInt>(dof_ptr->GetProgramWiseIndex(numbering_subset)));
processor_wise_dof_index_list_.push_back(dof_ptr->GetProcessorWiseOrGhostIndex(numbering_subset));
dof_value_list_.push_back(pair.second);
......
......@@ -91,6 +91,7 @@ namespace MoReFEM
switch(mpi_scale)
{
case MpiScale::program_wise:
std::cout << "======================= Local2GlobalStorage" << std::endl;
local_2_global_array.push_back(static_cast<PetscInt>(dof.GetProgramWiseIndex(numbering_subset)));
break;
......
......@@ -88,6 +88,7 @@ namespace MoReFEM
const auto proc_wise_index = static_cast<std::size_t>(dof.GetProcessorWiseOrGhostIndex(numbering_subset));
assert(proc_wise_index < static_cast<std::size_t>(Nrow_proc_wise));
assert(non_zero_slots_per_local_row[proc_wise_index].empty() && "Each should be filled once!");
std::cout << "=================== AllocateGlobalMatrix" << std::endl;
const auto program_wise_index = static_cast<PetscInt>(dof.GetProgramWiseIndex(numbering_subset));
non_zero_slots_per_local_row[proc_wise_index] = { program_wise_index };
}
......@@ -156,7 +157,10 @@ namespace MoReFEM
const auto& dof = *dof_ptr;
if (dof.IsInNumberingSubset(numbering_subset))
{
std::cout << "======================= AllocateGlobalVector" << std::endl;
ghosted_dof_index_list.push_back(static_cast<PetscInt>(dof.GetProgramWiseIndex(numbering_subset)));
}
}
}
......
......@@ -623,7 +623,8 @@ namespace MoReFEM
{
const auto& dof_ptr = dof_list[i];
assert(!(!dof_ptr));
std::cout << "======================= PrintDofInformation" << std::endl;
out << dof_ptr->GetProgramWiseIndex(numbering_subset) << ';';
out << dof_ptr->GetProcessorWiseOrGhostIndex(numbering_subset) << ';';
out << nature << ';';
......
......@@ -25,8 +25,8 @@ namespace MoReFEM
namespace FEltSpaceNS
{
void ComputeProcessorWiseDofIndexes(const NodeBearer::vector_shared_ptr& node_bearer_list,
DofNumberingScheme dof_numbering_scheme,
unsigned int& current_dof_index,
......@@ -113,6 +113,67 @@ namespace MoReFEM
}
void AssignNumberingSubsetDofIndexForPrepartitionedData
::Do(LuaOptionFile& god_of_dof_prepartitioned_data,
const Dof::vector_shared_ptr& processor_wise_dof_list,
const Dof::vector_shared_ptr& ghost_dof_list,
const NumberingSubset::vector_const_shared_ptr& numbering_subset_list)
{
std::cout << "DMLKF>Dfj;hlsjlkgjl;kgeklj" << std::endl;
for (const auto& numbering_subset_ptr : numbering_subset_list)
{
assert(!(!numbering_subset_ptr));
const auto& numbering_subset = *numbering_subset_ptr;
const std::string lua_key = "program_wise_dof_index_for_numbering_subset_"
+ std::to_string(numbering_subset.GetUniqueId());
std::vector<unsigned int> dof_index_list;
god_of_dof_prepartitioned_data.Read(lua_key,
"",
dof_index_list,
__FILE__, __LINE__);
auto it = dof_index_list.cbegin();
const auto end = dof_index_list.cend();
ReassignNumberingSubsetIndex(numbering_subset,
processor_wise_dof_list,
it,
end);
ReassignNumberingSubsetIndex(numbering_subset,
ghost_dof_list,
it,
end);
assert(it == end && "The data in the prepartition data file should cover exactly the number of "
"reconstructed dofs in the numbering subset.");
}
}
void AssignNumberingSubsetDofIndexForPrepartitionedData
::ReassignNumberingSubsetIndex(const NumberingSubset& numbering_subset,
const Dof::vector_shared_ptr& dof_list,
std::vector<unsigned int>::const_iterator& dof_index_it,
const std::vector<unsigned int>::const_iterator& dof_index_end)
{
static_cast<void>(dof_index_end);
for (const auto& dof_ptr : dof_list)
{
assert(!(!dof_ptr));
auto& dof = *dof_ptr;
if (dof.IsInNumberingSubset(numbering_subset))
{
assert(dof_index_it != dof_index_end);
dof.SetProgramWiseIndex(numbering_subset, *dof_index_it);
++dof_index_it;
}
}
}
......
......@@ -124,6 +124,30 @@ namespace MoReFEM
ComputeDofIndexListPerFEltSpace(const FEltSpace::vector_unique_ptr& felt_space_list);
/*!
* \brief Helper to reassign properly the program-wise indexes of \a Dof within a given \a NumberingSubset in the case of a run from
* prepartitioned data.
*/
struct AssignNumberingSubsetDofIndexForPrepartitionedData
{
public:
//! The static method which does the job.
static void Do(LuaOptionFile& god_of_dof_prepartitioned_data,
const Dof::vector_shared_ptr& processor_wise_dof_list,
const Dof::vector_shared_ptr& ghost_dof_list,
const NumberingSubset::vector_const_shared_ptr& numbering_subset_list);
private:
static void ReassignNumberingSubsetIndex(const NumberingSubset& numbering_subset,
const Dof::vector_shared_ptr& dof_list,
std::vector<unsigned int>::const_iterator& dof_index_it,
const std::vector<unsigned int>::const_iterator& dof_index_end);
};
} // namespace FEltSpaceNS
......
......@@ -105,6 +105,7 @@ namespace MoReFEM
{
assert(!(!dof_ptr));
const auto& dof = *dof_ptr;
std::cout << "DofProgramWiseIndexListPerVertexCoordIndexList" << std::endl;
index_list.push_back(dof.GetProgramWiseIndex(numbering_subset));
++Ndof;
......
......@@ -96,13 +96,33 @@ namespace MoReFEM
break;
case TypeDofIndex::processor_wise_per_numbering_subset:
assert(!(!numbering_subset_ptr));
# ifndef NDEBUG
{
assert(!(!numbering_subset_ptr));
const auto numbering_subset_id = numbering_subset_ptr->GetUniqueId();
decltype(auto) program_wise_index_per_numbering_subset =
dof.GetProgramWiseIndexPerNumberingSubset();
const auto it = std::find_if(program_wise_index_per_numbering_subset.cbegin(),
program_wise_index_per_numbering_subset.cend(),
[numbering_subset_id](const auto& pair)
{
return pair.first == numbering_subset_id;
});
assert(it != program_wise_index_per_numbering_subset.cend()
&& "To avoid inconsistent object, it is mandatory that the "
"program-wise index for a Dof in a NumberingSubset exists before "
"adding the processor-wise one.");
}
# endif // NDEBUG
dof.SetProcessorWiseOrGhostIndex(*numbering_subset_ptr, current_dof_index);
break;
case TypeDofIndex::processor_wise:
assert(!numbering_subset_ptr && "No numbering subset are expected for this case!");
dof.SetInternalProcessorWiseOrGhostIndex(current_dof_index);
break;
}
switch(dof_numbering_scheme)
......
......@@ -33,6 +33,16 @@ namespace MoReFEM::Internal::GodOfDofNS
// Useful only for ghosts.
std::vector<unsigned int> GenerateMpiRankList(const NodeBearer::vector_shared_ptr& ghost_node_bearer_list);
// Generate the lists of program-wise indexes for \a numbering subset.
std::vector<unsigned int>
GenerateProgramWiseDofIndexesForNumberingSubset(const GodOfDof& god_of_dof,
const NumberingSubset& numbering_subset);
//! Extract in \a out the program-wise indexes of elements of \a dof_list that are WITHIN \a NumberingSubset .
void GenerateProgramWiseDofList(const NumberingSubset& numbering_subset,
const Dof::vector_shared_ptr& dof_list,
std::vector<unsigned int>& out);
} // namespace anonymous
......@@ -90,11 +100,29 @@ namespace MoReFEM::Internal::GodOfDofNS
using lua_map_policy =
Utilities::PrintPolicyNS::Associative<Utilities::PrintPolicyNS::associative_format::Lua>;
Utilities::PrintContainer<lua_map_policy>
::Do(god_of_dof.NprogramWiseDofPerNumberingSubset(), out, ", ", "{ ", " } ");
out <<std::endl;
}
out << "\n-- For each numbering subset, the list of the program-wise index of its dof." << std::endl;
out << "-- We are considered here the program-wise index INSIDE the NumberingSubset, which may differ "
<< "from the internal one defined regardless of the numbering subsets." << std::endl;
decltype(auto) numbering_subset_list = god_of_dof.GetNumberingSubsetList();
for (const auto& numbering_subset_ptr : numbering_subset_list)
{
assert(!(!numbering_subset_ptr));
const auto& numbering_subset = *numbering_subset_ptr;
out << "program_wise_dof_index_for_numbering_subset_" << numbering_subset.GetUniqueId() << " = ";
Utilities::PrintContainer<>::Do(GenerateProgramWiseDofIndexesForNumberingSubset(god_of_dof,
numbering_subset),
out, ", ", "{ ", " }");
out << std::endl;
}
}
}
......@@ -153,6 +181,50 @@ namespace MoReFEM::Internal::GodOfDofNS
}
void GenerateProgramWiseDofList(const NumberingSubset& numbering_subset,
const Dof::vector_shared_ptr& dof_list,
std::vector<unsigned int>& out)
{
for (const auto& dof_ptr : dof_list)
{
assert(!(!dof_ptr));
if (dof_ptr->IsInNumberingSubset(numbering_subset))
{
std::cout << "==================== GenerateProgramWiseDofList " << std::endl;
out.push_back(dof_ptr->GetProgramWiseIndex(numbering_subset));
}
}
}
std::vector<unsigned int>
GenerateProgramWiseDofIndexesForNumberingSubset(const GodOfDof& god_of_dof,
const NumberingSubset& numbering_subset)
{
std::vector<unsigned int> ret;
std::vector<unsigned int> dof_index_list;
const auto capacity_guess = god_of_dof.NprocessorWiseDof(numbering_subset) + 20ul; // arbitrary to avoid
// number of memory
// allocation steps.
dof_index_list.reserve(capacity_guess);
{
GenerateProgramWiseDofList(numbering_subset,
god_of_dof.GetProcessorWiseDofList(),
dof_index_list);
GenerateProgramWiseDofList(numbering_subset,
god_of_dof.GetGhostedDofList(),
dof_index_list);
}
assert(dof_index_list.size() >= god_of_dof.NprocessorWiseDof(numbering_subset));
return ret;
}
} // namespace anonymous
......
......@@ -295,21 +295,15 @@ namespace MoReFEM
SetNodeBearerLists(std::move(processor_wise_node_bearer_list), std::move(ghosted_node_bearer_list));
}
// ===============================================================================
// \todo #1443 Some stuff below really needs to be unified for the sake of DRY...
// ===============================================================================
decltype(auto) numbering_subset_list = GetNumberingSubsetList();
{
for (const auto& numbering_subset_ptr : numbering_subset_list)
{
unsigned int current_index = 0u;
Internal::FEltSpaceNS
::ComputeDofIndexesForNumberingSubset<MpiScale::program_wise>(GetProcessorWiseNodeBearerList(),
CurrentDofNumberingScheme(),
numbering_subset_ptr,
current_index);
}
}
Internal::FEltSpaceNS::AssignNumberingSubsetDofIndexForPrepartitionedData::Do(god_of_dof_prepartitioned_data,
GetProcessorWiseDofList(),
GetGhostedDofList(),
numbering_subset_list);
// Compute the number of program- and processor- wise dofs.
using type = Internal::FEltSpaceNS::NdofHolder;
......@@ -327,18 +321,18 @@ namespace MoReFEM
const auto dof_list_per_felt_space = Internal::FEltSpaceNS::ComputeDofIndexListPerFEltSpace(felt_space_list);
for (const auto& felt_space_ptr : felt_space_list)
{
auto& felt_space = *felt_space_ptr;
{
auto& felt_space = *felt_space_ptr;
const auto unique_id = felt_space.GetUniqueId();
const auto unique_id = felt_space.GetUniqueId();
auto it = dof_list_per_felt_space.find(unique_id);
assert(it != dof_list_per_felt_space.cend());
auto it = dof_list_per_felt_space.find(unique_id);
assert(it != dof_list_per_felt_space.cend());
const auto& dof_unique_id_list = it->second;
const auto& dof_unique_id_list = it->second;
felt_space.ComputeDofList(dof_unique_id_list);
}
felt_space.ComputeDofList(dof_unique_id_list);
}
std::cout << "================= matrix_pattern_per_numbering_subset_ =================" << std::endl;
std::cout << GetMpi().GetRankPreffix() << " " << felt_space_list.size() << "\t" << GetProcessorWiseNodeBearerList().size()
......
......@@ -13,6 +13,7 @@
#include <algorithm>
#include <iostream> // TMP #1443
#include "FiniteElement/Nodes_and_dofs/Dof.hpp"
#include "Core/NumberingSubset/NumberingSubset.hpp"
......@@ -90,6 +91,7 @@ namespace MoReFEM
unsigned int Dof::GetProgramWiseIndex(const NumberingSubset& numbering_subset) const
{
std::cout << " Dof::GetProgramWiseIndex" << std::endl;
return FindInStorage(GetProgramWiseIndexPerNumberingSubset(), numbering_subset);
}
......@@ -97,6 +99,12 @@ namespace MoReFEM
bool Dof::IsInNumberingSubset(const NumberingSubset& numbering_subset) const
{
const auto& program_wise_index_per_numbering_subset = GetProgramWiseIndexPerNumberingSubset();
// This shouldn't happen (a Dof should be related to at least one NumberingSubset) but it help some tests to
// allow it in this function call (it leads to error messages easier to use to debug).
if (program_wise_index_per_numbering_subset.empty())
return false;
return Iterator(program_wise_index_per_numbering_subset, numbering_subset)
!= program_wise_index_per_numbering_subset.cend();
}
......@@ -147,6 +155,7 @@ namespace MoReFEM
unsigned int FindInStorage(const std::vector<std::pair<unsigned int, unsigned int>>& storage,
const NumberingSubset& numbering_subset)
{
std::cout << "2 - N in program_wise_index_per_numbering_subset = " << storage.size() << std::endl;
auto it = Iterator(storage, numbering_subset);
assert(it != storage.cend());
return it->second;
......
......@@ -37,15 +37,25 @@ namespace MoReFEM
class NumberingSubset;
class NodeBearer;
namespace Internal::FEltSpaceNS::Impl
namespace Internal::FEltSpaceNS
{
struct ComputeDofIndexesHelper;
struct AssignNumberingSubsetDofIndexForPrepartitionedData;
namespace Impl
{
struct ComputeDofIndexesHelper;
}
} // namespace Impl
} // namespace Internal::FEltSpaceNS
// ============================
......@@ -84,6 +94,9 @@ namespace MoReFEM
//! Friendship to the class which sets up the internal indexes.
friend struct Internal::FEltSpaceNS::Impl::ComputeDofIndexesHelper;
//! Friendship to reassign some dof indexes in the case of a run from prepartitioned data.
friend Internal::FEltSpaceNS::AssignNumberingSubsetDofIndexForPrepartitionedData;
public:
/// \name Special members.
......
......@@ -234,6 +234,20 @@ namespace MoReFEM
//! Return the list of nodes.
const Node::vector_shared_ptr& GetNodeList() const noexcept;
/*!
* \brief Whether the \a NodeBearer is a ghost or not.
*
* \attention This method is intended to be called ONLY once the partitioning is fully done (but if you're not a developer of the library you shouldn't
* bother as the partitioning occurs during \a Model::Initialize() or \a Model::Run() calls which should be one of your very first line of code in the main).
*
* This is actually a simple test upon the processor: if processor is same as rank it is not a ghost.
*
* \copydetails doxygen_hide_mpi_param
*
* \return True if the \a NodeBearer is a ghost of a \a NodeBearer handled by another mpi rank.
*/
bool IsGhost(const Wrappers::Mpi& mpi) const noexcept;
private:
......
......@@ -78,6 +78,12 @@ namespace MoReFEM
}
inline bool NodeBearer::IsGhost(const Wrappers::Mpi& mpi) const noexcept
{
return GetProcessor() != mpi.GetRank<unsigned int>();
}
} // namespace MoReFEM
......
......@@ -238,20 +238,43 @@ namespace MoReFEM::TestNS::LoadPrepartitionedGodOfDofNS
for (auto i = 0ul; i < size; ++i)
{
decltype(auto) original_dof = original_dof_list[i];
decltype(auto) reconstructed_dof = reconstructed_dof_list[i];
assert(!(!original_dof));
assert(!(!reconstructed_dof));
BOOST_CHECK_EQUAL(original_dof->GetInternalProcessorWiseOrGhostIndex(),
reconstructed_dof->GetInternalProcessorWiseOrGhostIndex());
BOOST_CHECK_EQUAL(original_dof->GetProgramWiseIndex(numbering_subset),
reconstructed_dof->GetProgramWiseIndex(numbering_subset));
BOOST_CHECK_EQUAL(original_dof->GetProcessorWiseOrGhostIndex(numbering_subset),
reconstructed_dof->GetProcessorWiseOrGhostIndex(numbering_subset));
decltype(auto) original_dof_ptr = original_dof_list[i];
decltype(auto) reconstructed_dof_ptr = reconstructed_dof_list[i];
assert(!(!original_dof_ptr));
assert(!(!reconstructed_dof_ptr));
const auto& original_dof = *original_dof_ptr;
const auto& reconstructed_dof = *reconstructed_dof_ptr;
BOOST_CHECK_EQUAL(original_dof.GetInternalProcessorWiseOrGhostIndex(),
reconstructed_dof.GetInternalProcessorWiseOrGhostIndex());
if (original_dof.IsInNumberingSubset(numbering_subset))
{
BOOST_CHECK(reconstructed_dof.IsInNumberingSubset(numbering_subset));
if (!reconstructed_dof.IsInNumberingSubset(numbering_subset))
{
std::cout << "WRONG!" << std::endl;
continue;
}
std::cout << "Orig proc " << original_dof.GetProcessorWiseOrGhostIndex(numbering_subset) << std::endl;
std::cout << "Recons proc = " << reconstructed_dof.GetProcessorWiseOrGhostIndex(numbering_subset) << std::endl;
BOOST_CHECK_EQUAL(original_dof.GetProcessorWiseOrGhostIndex(numbering_subset),
reconstructed_dof.GetProcessorWiseOrGhostIndex(numbering_subset));
std::cout << "Orig = " << original_dof.GetProgramWiseIndex(numbering_subset) << std::endl;
std::cout << "Recons = " << reconstructed_dof.GetProgramWiseIndex(numbering_subset) << std::endl;
BOOST_CHECK_EQUAL(original_dof.GetProgramWiseIndex(numbering_subset),
reconstructed_dof.GetProgramWiseIndex(numbering_subset));
}
else
{
BOOST_CHECK(!reconstructed_dof.IsInNumberingSubset(numbering_subset));
}
}
}
}
......
......@@ -291,7 +291,6 @@ namespace MoReFEM
invoking_file, invoking_line);
lua_pop(state_, 3);
}
for (const auto& elem : map)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment