Commit b660aeff authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

#531 LocalFEltSpace: store the local2global involving several unknowns.

parent 971606fa
......@@ -82,6 +82,68 @@ namespace HappyHeart
}
}
const std::vector<PetscInt>& LocalFEltSpace
::GetProgramWiseLocal2Global(const Unknown::vector_const_shared_ptr& list) const
{
const auto Nunknown = list.size();
// Special case on only 1 unknown (to space memory: no need to store it here in LocalFEltSpace when
// it's already available in FElt class).
if (Nunknown == 1ul)
{
assert(!(!list.back()));
return GetFiniteElt(*list.back()).GetLocal2Global<MpiScale::program_wise>();
}
std::lock_guard<std::mutex> lock(GetMutex());
const auto end = local_2_global_per_unknown_.cend();
auto it = std::find_if(local_2_global_per_unknown_.cbegin(),
end,
[Nunknown, &list](const auto& item)
{
const auto& unknown_list = item.first;
// Quick test upon size.
if (unknown_list.size() != Nunknown)
return false;
// Check equality component per component.
for (std::size_t i = 0ul; i < Nunknown; ++i)
{
if (*list[i] != *unknown_list[i])
return false;
}
return true;
});
if (it != end)
return it->second;
// Compute the value and then store it.
std::vector<PetscInt> new_entry;
for (const auto& item_ptr : list)
{
assert(!(!item_ptr));
const auto& item = *item_ptr;
const auto& felt = GetFiniteElt(item);
const auto& felt_loc2glob = felt.GetLocal2Global<MpiScale::program_wise>();
std::copy(felt_loc2glob.cbegin(),
felt_loc2glob.cend(),
std::back_inserter(new_entry));
}
local_2_global_per_unknown_.emplace_back(std::make_pair(list, std::move(new_entry)));
return local_2_global_per_unknown_.back().second;
}
......
......@@ -12,7 +12,7 @@
# include <memory>
# include <vector>
# include "Utilities/Mutex/Mutex.hpp"
# include "ThirdParty/IncludeWithoutWarning/Petsc/PetscSys.hpp"
# include "Geometry/GeometricElt.hpp"
......@@ -32,7 +32,7 @@ namespace HappyHeart
* There might be several: there is in fact one FiniteElt per Unknown present in the LocalFEltSpace.
*
*/
class LocalFEltSpace final
class LocalFEltSpace final : private Crtp::Mutex<LocalFEltSpace>
{
public:
......@@ -112,11 +112,11 @@ namespace HappyHeart
/*
*
* \todo #531 Improve the prototype: the std::vector should be allocated once in the class (with of course
* possibly several of them...). Mutable trick should be use here.
* \brief Get the program-wise local2global for the \a list given in input.
*
* If first call, the entry is computed, otherwise the value is read directly.
*/
template<MpiScale MpiScaleT>
std::vector<PetscInt> ComputeLocal2Global(const Unknown::vector_const_shared_ptr& list) const;
const std::vector<PetscInt>& GetProgramWiseLocal2Global(const Unknown::vector_const_shared_ptr& list) const;
private:
......@@ -134,6 +134,13 @@ namespace HappyHeart
//! List of nodes that belong to the FiniteElt.
NodeBearer::vector_shared_ptr node_bearer_list_;
/*!
* \brief Store the program-wise local2global for eachlist of unknowns.
*
* Entries are generated the first time they are needed; hence the 'mutable' here.
*/
mutable std::vector<std::pair<Unknown::vector_const_shared_ptr, std::vector<PetscInt>>> local_2_global_per_unknown_;
# ifndef NDEBUG
......
......@@ -77,32 +77,6 @@ namespace HappyHeart
}
template<MpiScale MpiScaleT>
std::vector<PetscInt> LocalFEltSpace
::ComputeLocal2Global(const Unknown::vector_const_shared_ptr& list) const
{
std::vector<PetscInt> ret;
for (const auto& item_ptr : list)
{
assert(!(!item_ptr));
const auto& item = *item_ptr;
const auto& felt = GetFiniteElt(item);
const auto& felt_loc2glob = felt.GetLocal2Global<MpiScaleT>();
std::copy(felt_loc2glob.cbegin(),
felt_loc2glob.cend(),
std::back_inserter(ret));
}
return ret;
}
} // namespace HappyHeart
......
......@@ -105,7 +105,7 @@ namespace HappyHeart
decltype(auto) row_local_2_global =
local_felt_space.ComputeLocal2Global<MpiScale::program_wise>(row_unknown_list);
local_felt_space.GetProgramWiseLocal2Global(row_unknown_list);
assert(static_cast<int>(row_local_2_global.size()) == local_matrix.GetM());
......@@ -124,7 +124,7 @@ namespace HappyHeart
decltype(auto) col_unknown_list = local_variational_operator.GetUnknownList(col_numbering_subset);
decltype(auto) col_local_2_global =
local_felt_space.ComputeLocal2Global<MpiScale::program_wise>(col_unknown_list);
local_felt_space.GetProgramWiseLocal2Global(col_unknown_list);
assert(static_cast<int>(col_local_2_global.size()) == local_matrix.GetN());
......@@ -247,7 +247,7 @@ namespace HappyHeart
decltype(auto) unknown_list = local_variational_operator.GetUnknownList(numbering_subset);
decltype(auto) local_2_global =
local_felt_space.ComputeLocal2Global<MpiScale::program_wise>(unknown_list);
local_felt_space.GetProgramWiseLocal2Global(unknown_list);
assert(static_cast<int>(local_2_global.size()) == local_vector.GetSize());
......
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