From e1702fdba4f0d9a07f07a53587678ef6617de605 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Mon, 19 Feb 2024 12:58:25 +0100 Subject: [PATCH 01/26] implement set_address_identity_function --- .../set_address_identity_function.h | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 kratos/containers/set_address_identity_function.h diff --git a/kratos/containers/set_address_identity_function.h b/kratos/containers/set_address_identity_function.h new file mode 100644 index 000000000000..532b7f0bcab9 --- /dev/null +++ b/kratos/containers/set_address_identity_function.h @@ -0,0 +1,70 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// Suneth Warnakulasuriya +// +// + +#pragma once + +// System includes +#include + +// External includes + +// Project includes + +namespace Kratos +{ +///@name Kratos Classes +///@{ + +/** + * @class SetAddressIdentityFunction + * @brief A functor that serves as the identity function for memory locations. + * @details This class provides two overloaded operator() functions, one for non-const objects + * and another for const objects. The operator() returns the input objects memory location as it is, + * effectively acting as an identity function for address. + * The purpose of this functor is to allow objects' memory locations to be used as keys in sets or other + * containers that require comparison. By using this functor, you can avoid defining + * custom comparison functions or operators when the object itself can be considered + * for comparison. + * @tparam TDataType The data type of the object that the functor operates on. + * @author Pooyan Dadvand + * @author Suneth Warnakulasuriya + */ +template +class SetAddressIdentityFunction +{ +public: + /** + * @brief Operator that returns a non-const reference pointer to the input object. + * @param data The input object of type TDataType. + * @return A non-const reference pointer to the same object as provided in the parameter. + */ + TDataType* operator()(TDataType& data) + { + return &data; + } + + /** + * @brief Operator that returns a const reference pointer to the input object. + * @param data The input object of type TDataType. + * @return A const reference pointer to the same object as provided in the parameter. + */ + TDataType const * operator()(const TDataType& data) const + { + return &data; + } +}; + +///@} + +} // namespace Kratos. From 05202609dbb8ac853913e4764bc5e74e32e468cb Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Mon, 19 Feb 2024 12:58:41 +0100 Subject: [PATCH 02/26] use set_address_identity_function --- kratos/containers/pointer_vector_set.h | 24 +++++------ ...tion_builder_and_solver_with_constraints.h | 40 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index eb8ce3b03af4..525fa9d083ae 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -27,7 +27,7 @@ // Project includes #include "includes/define.h" #include "includes/serializer.h" -#include "containers/set_identity_function.h" +#include "containers/set_address_identity_function.h" namespace Kratos { @@ -63,7 +63,7 @@ namespace Kratos * @author Pooyan Dadvand */ template, + class TGetKeyType = SetAddressIdentityFunction, class TCompareType = std::less()(std::declval()))>, class TEqualType = std::equal_to()(std::declval()))>, class TPointerType = typename TDataType::Pointer, @@ -136,7 +136,7 @@ class PointerVectorSet final */ PointerVectorSet(const PointerVectorSet& rOther) : mData(rOther.mData), mSortedPartSize(rOther.mSortedPartSize), mMaxBufferSize(rOther.mMaxBufferSize) {} - + /** * @brief Constructs a PointerVectorSet from a container. * @details This constructor initializes a PointerVectorSet with elements from a container. @@ -789,15 +789,15 @@ class PointerVectorSet final /** * @brief Get the maximum size of buffer used in the container */ - size_type GetMaxBufferSize() const + size_type GetMaxBufferSize() const { return mMaxBufferSize; } - /** + /** * @brief Set the maximum size of buffer used in the container. * @details This container uses a buffer which keep data unsorted. After buffer size arrived to the MaxBufferSize it will sort all container and empties buffer. - * @param NewSize Is the new buffer maximum size. + * @param NewSize Is the new buffer maximum size. */ void SetMaxBufferSize(const size_type NewSize) { @@ -805,16 +805,16 @@ class PointerVectorSet final } /** - * @brief Get the sorted part size of buffer used in the container. + * @brief Get the sorted part size of buffer used in the container. */ - size_type GetSortedPartSize() const + size_type GetSortedPartSize() const { return mSortedPartSize; } - /** + /** * @brief Set the sorted part size of buffer used in the container. - * @param NewSize Is the new buffer maximum size. + * @param NewSize Is the new buffer maximum size. */ void SetSortedPartSize(const size_type NewSize) { @@ -980,10 +980,10 @@ class PointerVectorSet final /// The data container holding the elements. TContainerType mData; - + /// The size of the sorted portion of the data. size_type mSortedPartSize; - + /// The maximum buffer size for data storage. size_type mMaxBufferSize; diff --git a/kratos/solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver_with_constraints.h b/kratos/solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver_with_constraints.h index f4e45f848f4a..de9a9e1fdfd4 100644 --- a/kratos/solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver_with_constraints.h +++ b/kratos/solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver_with_constraints.h @@ -554,8 +554,8 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints if (BaseType::mCalculateReactionsFlag) { for (auto& r_dof : BaseType::mDofSet) { - const bool is_master_fixed = mDoFMasterFixedSet.find(r_dof) == mDoFMasterFixedSet.end() ? false : true; - const bool is_slave = mDoFSlaveSet.find(r_dof) == mDoFSlaveSet.end() ? false : true; + const bool is_master_fixed = mDoFMasterFixedSet.find(&r_dof) == mDoFMasterFixedSet.end() ? false : true; + const bool is_slave = mDoFSlaveSet.find(&r_dof) == mDoFSlaveSet.end() ? false : true; if (is_master_fixed || is_slave) { // Fixed or MPC dof const IndexType equation_id = r_dof.EquationId(); r_reactions_vector[mReactionEquationIdMap[equation_id]] += rb[equation_id]; @@ -741,7 +741,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints aux_dof_set.reserve(mDoFToSolveSystemSize); for (auto& r_dof : BaseType::mDofSet) { if (r_dof.EquationId() < BaseType::mEquationSystemSize) { - auto it = mDoFSlaveSet.find(r_dof); + auto it = mDoFSlaveSet.find(&r_dof); if (it == mDoFSlaveSet.end()) aux_dof_set.push_back( &r_dof ); } @@ -966,7 +966,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints for (auto& dof : BaseType::mDofSet) { if (dof.EquationId() < BaseType::mEquationSystemSize) { const IndexType equation_id = dof.EquationId(); - auto it = mDoFSlaveSet.find(dof); + auto it = mDoFSlaveSet.find(&dof); if (it == mDoFSlaveSet.end()) { solvable_dof_reorder.insert(IndexIndexPairType(equation_id, counter)); master_indices.insert(IndexIndexSetPairType(equation_id, IndexSetType({counter}))); @@ -1318,7 +1318,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints // Updating variables for (auto& r_dof : BaseType::mDofSet) { - if ((r_dof.IsFixed()) || mDoFSlaveSet.find(r_dof) != mDoFSlaveSet.end()) { + if ((r_dof.IsFixed()) || mDoFSlaveSet.find(&r_dof) != mDoFSlaveSet.end()) { r_dof.GetSolutionStepReactionValue() = -r_reactions_vector[mReactionEquationIdMap[r_dof.EquationId()]]; } } @@ -1356,11 +1356,11 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints auto it_dof = it_dof_begin + i; const IndexType equation_id = it_dof->EquationId(); if (equation_id < BaseType::mEquationSystemSize ) { - auto it_first_check = mDoFSlaveSet.find(*it_dof); + auto it_first_check = mDoFSlaveSet.find(&*it_dof); if (it_first_check == mDoFSlaveSet.end()) { - auto it_second_check = mDoFSlaveSet.find(*it_dof); + auto it_second_check = mDoFSlaveSet.find(&*it_dof); if (it_second_check == mDoFSlaveSet.end()) { - if(mDoFMasterFixedSet.find(*it_dof) == mDoFMasterFixedSet.end()) { + if(mDoFMasterFixedSet.find(&*it_dof) == mDoFMasterFixedSet.end()) { scaling_factors[counter] = 1.0; } } @@ -1564,7 +1564,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints for (auto& dof : BaseType::mDofSet) { if (dof.IsFixed()) { - auto it = mDoFMasterFixedSet.find(dof); + auto it = mDoFMasterFixedSet.find(&dof); if (it == mDoFMasterFixedSet.end()) { dof.SetEquationId(--fix_id); } else { @@ -1581,7 +1581,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints IndexType counter = 0; for (auto& dof : BaseType::mDofSet) { if (dof.EquationId() < BaseType::mEquationSystemSize) { - auto it = mDoFSlaveSet.find(dof); + auto it = mDoFSlaveSet.find(&dof); if (it == mDoFSlaveSet.end()) { ++counter; } @@ -1594,8 +1594,8 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints // Finally we build the relation between the EquationID and the component of the reaction counter = 0; for (auto& r_dof : BaseType::mDofSet) { - const bool is_master_fixed = mDoFMasterFixedSet.find(r_dof) == mDoFMasterFixedSet.end() ? false : true; - const bool is_slave = mDoFSlaveSet.find(r_dof) == mDoFSlaveSet.end() ? false : true; + const bool is_master_fixed = mDoFMasterFixedSet.find(&r_dof) == mDoFMasterFixedSet.end() ? false : true; + const bool is_slave = mDoFSlaveSet.find(&r_dof) == mDoFSlaveSet.end() ? false : true; if (is_master_fixed || is_slave) { // Fixed or MPC dof mReactionEquationIdMap.insert({r_dof.EquationId(), counter}); ++counter; @@ -1660,7 +1660,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints auto it_dof = it_dof_begin + i; const IndexType equation_id = it_dof->EquationId(); if (equation_id < BaseType::mEquationSystemSize ) { - auto it = mDoFSlaveSet.find(*it_dof); + auto it = mDoFSlaveSet.find(&*it_dof); if (it == mDoFSlaveSet.end()) { current_solution[counter] = it_dof->GetSolutionStepValue() + rDxSolved[counter]; counter += 1; @@ -1936,8 +1936,8 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints const IndexType i_global = rEquationId[i_local]; auto it_dof = BaseType::mDofSet.begin() + i_global; - const bool is_master_fixed = mDoFMasterFixedSet.find(*it_dof) == mDoFMasterFixedSet.end() ? false : true; - const bool is_slave = mDoFSlaveSet.find(*it_dof) == mDoFSlaveSet.end() ? false : true; + const bool is_master_fixed = mDoFMasterFixedSet.find(&*it_dof) == mDoFMasterFixedSet.end() ? false : true; + const bool is_slave = mDoFSlaveSet.find(&*it_dof) == mDoFSlaveSet.end() ? false : true; if (is_master_fixed || is_slave) { // Fixed or MPC dof double& r_b_value = r_reactions_vector[mReactionEquationIdMap[i_global]]; const double rhs_value = rRHSContribution[i_local]; @@ -1974,7 +1974,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints for (auto& dof : BaseType::mDofSet) { if (dof.EquationId() < BaseType::mEquationSystemSize) { const IndexType equation_id = dof.EquationId(); - auto it = mDoFSlaveSet.find(dof); + auto it = mDoFSlaveSet.find(&dof); if (it == mDoFSlaveSet.end()) { solvable_dof_reorder.insert(IndexIndexPairType(equation_id, counter)); ++counter; @@ -2014,9 +2014,9 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints IndexPartition(mDoFToSolveSystemSize).for_each([&, this](std::size_t Index){ auto it_dof = it_dof_begin + Index; if (Index < this->mEquationSystemSize) { - auto it = mDoFSlaveSet.find(*it_dof); + auto it = mDoFSlaveSet.find(&*it_dof); if (it == mDoFSlaveSet.end()) { - if(mDoFMasterFixedSet.find(*it_dof) != mDoFMasterFixedSet.end()) { + if(mDoFMasterFixedSet.find(&*it_dof) != mDoFMasterFixedSet.end()) { rb[Index] = 0.0; } } @@ -2064,7 +2064,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints for (auto& dof : BaseType::mDofSet) { if (dof.EquationId() < BaseType::mEquationSystemSize) { const IndexType equation_id = dof.EquationId(); - auto it = mDoFSlaveSet.find(dof); + auto it = mDoFSlaveSet.find(&dof); if (it == mDoFSlaveSet.end()) { solvable_dof_reorder.insert(IndexIndexPairType(equation_id, counter)); ++counter; @@ -2192,7 +2192,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints const IndexType equation_id = it_dof->EquationId(); if (equation_id < BaseType::mEquationSystemSize ) { - auto it = mDoFSlaveSet.find(*it_dof); + auto it = mDoFSlaveSet.find(&*it_dof); if (it == mDoFSlaveSet.end()) { u_bar[counter] = it_dof->GetSolutionStepValue() + rDxSolved[counter]; counter += 1; From abaeedd42dcf23d5fdc4feac0a623d0507359b28 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Mon, 19 Feb 2024 14:42:29 +0100 Subject: [PATCH 03/26] add insert methods to ptrvecset --- kratos/containers/pointer_vector_set.h | 128 ++++++++++++++++++------- 1 file changed, 91 insertions(+), 37 deletions(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index 525fa9d083ae..dd4ef5c95c52 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -126,8 +126,8 @@ class PointerVectorSet final PointerVectorSet(TInputIteratorType First, TInputIteratorType Last, size_type NewMaxBufferSize = 1) : mSortedPartSize(size_type()), mMaxBufferSize(NewMaxBufferSize) { - for (; First != Last; ++First) - insert(begin(), *First); + mData.reserve(std::distance(First, Last)); + insert(First, Last); } /** @@ -558,54 +558,108 @@ class PointerVectorSet final mSortedPartSize = mData.size(); } - /** - * @brief Inserts a pointer at the specified position. - * @details This function inserts a given pointer at the specified position in the set. It also maintains - * the sorting order and updates mSortedPartSize if necessary. - * @param Position An iterator pointing to the position where the pointer should be inserted. - * @param pData The pointer to be inserted. + /** + * @brief Inserts a pointer. + * @details This function inserts a given pointer such that the resulting PointerVectorSet + * is kept sorted. If there exists already a pointer with a key same as the key of the value, then + * this will return iterator of that existing pointer (The value will not be inserted.) + * @param value The pointer to be inserted. * @return An iterator pointing to the inserted element. */ - iterator insert(iterator Position, const TPointerType pData) - { - ptr_iterator sorted_part_end; - - key_type key = KeyOf(*pData); - - if (mData.size() - mSortedPartSize >= mMaxBufferSize) { - Sort(); - sorted_part_end = mData.end(); - } else - sorted_part_end = mData.begin() + mSortedPartSize; - - ptr_iterator i(std::lower_bound(mData.begin(), sorted_part_end, key, CompareKey())); - if (i == sorted_part_end) { - mSortedPartSize++; - return mData.insert(sorted_part_end, pData); + iterator insert(const TPointerType& value) + { + auto itr_pos = std::lower_bound(mData.begin(), mData.end(), KeyOf(*value), CompareKey()); + if (itr_pos == mData.end()) { + // the position to insert is at the end. + mData.push_back(value); + return iterator(mData.end() - 1); + } else if (EqualKeyTo(KeyOf(*value))(*itr_pos)) { + // already found existing element with the same key, hence returning the existing element. + return iterator(itr_pos); + } else { + // insert the new value before the itr_pos. + return mData.insert(itr_pos, value); } + } - if (!EqualKeyTo(key)(*i)) - if ((i = std::find_if(sorted_part_end, mData.end(), EqualKeyTo(key))) == mData.end()) { - mData.push_back(pData); + /** + * @brief Inserts a pointer at the specified position. + * @details This function inserts a given pointer. If the given position_hint is valid, then + * it uses that to insert the value, otherwise the position_hint is discarded to maintain the dataset + * sorted. If there is an existing element with the same key as in the value, then an iterator for + * the existing element is returned. + * @param position_hint An iterator pointing to the position where the pointer may be inserted. + * @param value The pointer to be inserted. + * @return An iterator pointing to the inserted element. + */ + iterator insert(const_iterator position_hint, const TPointerType& value) + { + if (empty()) { + // the dataset is empty. So use push back. + mData.push_back(value); + return iterator(mData.end() - 1); + } else if (position_hint == cend()) { + // trying to insert at the end. + if (KeyOf(*(position_hint - 1)) < KeyOf(*value)) { + // key at the position hint is less than the value of key. Hence position hint + // is valid. So using the push back. + mData.push_back(value); return iterator(mData.end() - 1); + } else { + // given position is invalid. Hence, discarding the hint. + return insert(value); } - - *i = pData; - return i; + } else if (EqualKeyTo(KeyOf(*position_hint))(*ptr_begin())) { + // trying to insert at the front. + if (KeyOf(*value) < KeyOf(*position_hint)) { + // key at the position hint is greater than the value of key. Hence position hint + // is valid. So using the push back. + return mData.insert(mData.begin(), value); + } else { + // given position is invalid. Hence, discarding the hint. + return insert(value); + } + } else { + // trying to insert at an arbitrary position. + if (KeyOf(*value) < KeyOf(*position_hint) && (KeyOf(*(position_hint - 1)) < KeyOf(*value))) { + return mData.insert(mData.begin() + (position_hint - cbegin()), value); + } else { + // given position is invalid. Hence, discarding the hint. + return insert(value); + } + } } /** * @brief Insert elements from a range of iterators. - * @details This function inserts elements from a range defined by the iterators `First` and `Last` - * into the set. It uses the `insert` function to insert each element. - * @param First An input iterator pointing to the beginning of the range to insert. - * @param Last An input iterator pointing to the end of the range to insert. + * @details This function inserts element pointers from a range defined by the iterators `first` and `last` + * into the set. This will not insert any elements in the range, if there exists an element with a key + * which is equal to an element's key in the input range. + * @param first An input iterator pointing to the beginning of the range to insert. + * @param last An input iterator pointing to the end of the range to insert. */ template - void insert(InputIterator First, InputIterator Last) + void insert(InputIterator first, InputIterator last) { - for (; First != Last; ++First) - insert(begin(), *First); + // first sorts the input iterators and make the input unique. + std::sort(first, last, CompareKey()); + auto new_last = std::unique(first, last, EqualKeyTo()); + + if (empty()) { + for (; first != new_last; ++first) { + mData.push_back(*first); + } + } else { + auto p_current_itr = mData.begin(); + // now add the new elements + for (; first != new_last; ++first) { + // find the lower bound element. + p_current_itr = std::lower_bound(p_current_itr, mData.end(), KeyOf(**first), CompareKey()); + if (!EqualKeyTo(KeyOf(**first))(*p_current_itr)) { + p_current_itr = mData.insert(p_current_itr, *first); + } + } + } } /** From 4b34963e48cbaf7092b7de3044c3a998feec5101 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Mon, 19 Feb 2024 14:57:56 +0100 Subject: [PATCH 04/26] add insert tests --- .../containers/test_pointer_vector_set.cpp | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) diff --git a/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp b/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp index b8e062f26786..9ad5a8f0d8c4 100644 --- a/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp +++ b/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp @@ -42,6 +42,218 @@ KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetCBeginAndCEnd, KratosCoreFastSuite) KRATOS_EXPECT_EQ((test_container.cend()-1)->Id(), 3); } +KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert1, KratosCoreFastSuite) +{ + PointerVectorSet test_container; + auto p_element_1 = Kratos::make_intrusive(1); + auto p_element_2 = Kratos::make_intrusive(2); + auto p_element_3 = Kratos::make_intrusive(3); + auto p_element_4 = Kratos::make_intrusive(4); + auto p_element_5 = Kratos::make_intrusive(5); + auto p_element_6 = Kratos::make_intrusive(6); + auto p_element_3_ptr_copy = Kratos::intrusive_ptr(p_element_3); + test_container.insert(p_element_3); + test_container.insert(p_element_2); + test_container.insert(p_element_1); + test_container.insert(p_element_5); + test_container.insert(p_element_6); + test_container.insert(p_element_4); + test_container.insert(p_element_3_ptr_copy); + + KRATOS_EXPECT_EQ(test_container.size(), 6); + + auto itr = test_container.begin(); + for (; itr != test_container.end() - 1; ++itr) { + KRATOS_EXPECT_TRUE(&*(itr) - &*(itr + 1) < 0); + } +} + +KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert2, KratosCoreFastSuite) +{ + PointerVectorSet test_container; + auto p_element_1 = Kratos::make_intrusive(1); + auto p_element_2 = Kratos::make_intrusive(2); + auto p_element_3 = Kratos::make_intrusive(3); + auto p_element_4 = Kratos::make_intrusive(4); + auto p_element_5 = Kratos::make_intrusive(5); + auto p_element_6 = Kratos::make_intrusive(6); + auto p_element_3_copy = Kratos::make_intrusive(3); + test_container.insert(p_element_3); + test_container.insert(p_element_2); + test_container.insert(p_element_1); + test_container.insert(p_element_5); + test_container.insert(p_element_6); + test_container.insert(p_element_4); + test_container.insert(p_element_3_copy); + + KRATOS_EXPECT_EQ(test_container.size(), 6); + + auto itr = test_container.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_1); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_2); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_3); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_4); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_5); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_6); +} + +KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert3, KratosCoreFastSuite) +{ + PointerVectorSet test_container; + auto p_element_1 = Kratos::make_intrusive(1); + auto p_element_2 = Kratos::make_intrusive(2); + auto p_element_3 = Kratos::make_intrusive(3); + auto p_element_4 = Kratos::make_intrusive(4); + auto p_element_5 = Kratos::make_intrusive(5); + auto p_element_6 = Kratos::make_intrusive(6); + auto p_element_3_ptr_copy = Kratos::intrusive_ptr(p_element_3); + test_container.insert(test_container.end(), p_element_3); + test_container.insert(test_container.end(), p_element_6); + test_container.insert(test_container.end(), p_element_2); + test_container.insert(test_container.begin(), p_element_1); + test_container.insert(test_container.begin(), p_element_5); + test_container.insert(test_container.begin() + 3, p_element_4); + test_container.insert(test_container.begin() + 3, p_element_1); + + KRATOS_EXPECT_EQ(test_container.size(), 6); + + auto itr = test_container.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_1); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_2); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_3); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_4); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_5); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_6); +} + +KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert4, KratosCoreFastSuite) +{ + PointerVectorSet test_container; + auto p_element_1 = Kratos::make_intrusive(1); + auto p_element_2 = Kratos::make_intrusive(2); + auto p_element_3 = Kratos::make_intrusive(3); + auto p_element_4 = Kratos::make_intrusive(4); + auto p_element_5 = Kratos::make_intrusive(5); + auto p_element_6 = Kratos::make_intrusive(6); + auto p_element_3_copy = Kratos::make_intrusive(3); + + std::vector tmp; + tmp.push_back(p_element_2); + tmp.push_back(p_element_1); + tmp.push_back(p_element_4); + tmp.push_back(p_element_3); + tmp.push_back(p_element_4); + tmp.push_back(p_element_6); + tmp.push_back(p_element_1); + tmp.push_back(p_element_5); + tmp.push_back(p_element_3_copy); + test_container.insert(tmp.begin(), tmp.end()); + + KRATOS_EXPECT_EQ(test_container.size(), 6); + + auto itr = test_container.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_1); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_2); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_3); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_4); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_5); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_6); +} + +KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert5, KratosCoreFastSuite) +{ + PointerVectorSet test_container; + auto p_element_1 = Kratos::make_intrusive(1); + auto p_element_2 = Kratos::make_intrusive(2); + auto p_element_3 = Kratos::make_intrusive(3); + auto p_element_4 = Kratos::make_intrusive(4); + auto p_element_5 = Kratos::make_intrusive(5); + auto p_element_6 = Kratos::make_intrusive(6); + auto p_element_7 = Kratos::make_intrusive(7); + auto p_element_8 = Kratos::make_intrusive(8); + auto p_element_3_ptr_copy = Kratos::intrusive_ptr(p_element_3); + + std::vector tmp; + tmp.push_back(p_element_2); + tmp.push_back(p_element_1); + tmp.push_back(p_element_5); + tmp.push_back(p_element_8); + test_container.insert(tmp.begin(), tmp.end()); + + KRATOS_EXPECT_EQ(test_container.size(), 4); + auto itr = test_container.begin(); + for (; itr != test_container.end() - 1; ++itr) { + KRATOS_EXPECT_TRUE(&*(itr) - &*(itr + 1) < 0); + } + + tmp.clear(); + tmp.push_back(p_element_3); + tmp.push_back(p_element_4); + tmp.push_back(p_element_5); + tmp.push_back(p_element_3); + tmp.push_back(p_element_3_ptr_copy); + tmp.push_back(p_element_1); + tmp.push_back(p_element_7); + tmp.push_back(p_element_6); + test_container.insert(tmp.begin(), tmp.end()); + + KRATOS_EXPECT_EQ(test_container.size(), 8); + itr = test_container.begin(); + for (; itr != test_container.end() - 1; ++itr) { + KRATOS_EXPECT_TRUE(&*(itr) - &*(itr + 1) < 0); + } +} + +KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert6, KratosCoreFastSuite) +{ + PointerVectorSet test_container; + auto p_element_1 = Kratos::make_intrusive(1); + auto p_element_2 = Kratos::make_intrusive(2); + auto p_element_3 = Kratos::make_intrusive(3); + auto p_element_4 = Kratos::make_intrusive(4); + auto p_element_5 = Kratos::make_intrusive(5); + auto p_element_6 = Kratos::make_intrusive(6); + auto p_element_7 = Kratos::make_intrusive(7); + auto p_element_8 = Kratos::make_intrusive(8); + auto p_element_3_copy = Kratos::make_intrusive(3); + + std::vector tmp; + tmp.push_back(p_element_2); + tmp.push_back(p_element_1); + tmp.push_back(p_element_5); + tmp.push_back(p_element_8); + test_container.insert(tmp.begin(), tmp.end()); + + KRATOS_EXPECT_EQ(test_container.size(), 4); + auto itr = test_container.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_1); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_2); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_5); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_8); + + tmp.clear(); + tmp.push_back(p_element_3); + tmp.push_back(p_element_4); + tmp.push_back(p_element_5); + tmp.push_back(p_element_3); + tmp.push_back(p_element_3_copy); + tmp.push_back(p_element_1); + tmp.push_back(p_element_7); + tmp.push_back(p_element_6); + test_container.insert(tmp.begin(), tmp.end()); + + KRATOS_EXPECT_EQ(test_container.size(), 8); + itr = test_container.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_1); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_2); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_3); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_4); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_5); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_6); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_7); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_8); +} + KRATOS_TEST_CASE_IN_SUITE(TestPointerVectorSet, KratosCoreFastSuite) { // create model and model part From 1a226e4252b89aaee14918e7e8f4029269d30999 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Mon, 19 Feb 2024 23:50:05 +0100 Subject: [PATCH 05/26] set mSortedPartSize = mData.size() --- kratos/containers/pointer_vector_set.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index dd4ef5c95c52..329d6a665025 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -572,12 +572,14 @@ class PointerVectorSet final if (itr_pos == mData.end()) { // the position to insert is at the end. mData.push_back(value); + mSortedPartSize = mData.size(); return iterator(mData.end() - 1); } else if (EqualKeyTo(KeyOf(*value))(*itr_pos)) { // already found existing element with the same key, hence returning the existing element. return iterator(itr_pos); } else { // insert the new value before the itr_pos. + mSortedPartSize = mData.size() + 1; return mData.insert(itr_pos, value); } } @@ -597,6 +599,7 @@ class PointerVectorSet final if (empty()) { // the dataset is empty. So use push back. mData.push_back(value); + mSortedPartSize = mData.size(); return iterator(mData.end() - 1); } else if (position_hint == cend()) { // trying to insert at the end. @@ -604,6 +607,7 @@ class PointerVectorSet final // key at the position hint is less than the value of key. Hence position hint // is valid. So using the push back. mData.push_back(value); + mSortedPartSize = mData.size(); return iterator(mData.end() - 1); } else { // given position is invalid. Hence, discarding the hint. @@ -614,6 +618,7 @@ class PointerVectorSet final if (KeyOf(*value) < KeyOf(*position_hint)) { // key at the position hint is greater than the value of key. Hence position hint // is valid. So using the push back. + mSortedPartSize = mData.size() + 1; return mData.insert(mData.begin(), value); } else { // given position is invalid. Hence, discarding the hint. @@ -622,6 +627,7 @@ class PointerVectorSet final } else { // trying to insert at an arbitrary position. if (KeyOf(*value) < KeyOf(*position_hint) && (KeyOf(*(position_hint - 1)) < KeyOf(*value))) { + mSortedPartSize = mData.size() + 1; return mData.insert(mData.begin() + (position_hint - cbegin()), value); } else { // given position is invalid. Hence, discarding the hint. @@ -660,6 +666,11 @@ class PointerVectorSet final } } } + + // TODO: To be removed once push back is removed. + // insert assumes the PointerVectorSet is already sorted, + // hence mSortedPartSize should be mData.size() + mSortedPartSize = mData.size(); } /** From 770d666bb4e13bcaebcb410db3a7ef946443451b Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Mon, 19 Feb 2024 23:50:31 +0100 Subject: [PATCH 06/26] add the inserts to the end --- kratos/includes/mesh.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kratos/includes/mesh.h b/kratos/includes/mesh.h index 44defa7fc017..ef7ca348eb29 100644 --- a/kratos/includes/mesh.h +++ b/kratos/includes/mesh.h @@ -265,7 +265,7 @@ class Mesh : public DataValueContainer, public Flags */ void AddNode(typename NodeType::Pointer pNewNode) { - mpNodes->insert(mpNodes->begin(), pNewNode); + mpNodes->insert(mpNodes->end(), pNewNode); } /** Returns the Node::Pointer corresponding to it's identifier */ @@ -487,7 +487,7 @@ class Mesh : public DataValueContainer, public Flags */ void AddElement(typename ElementType::Pointer pNewElement) { - mpElements->insert(mpElements->begin(), pNewElement); + mpElements->insert(mpElements->end(), pNewElement); } /** Returns the Element::Pointer corresponding to it's identifier */ @@ -610,7 +610,7 @@ class Mesh : public DataValueContainer, public Flags */ void AddCondition(typename ConditionType::Pointer pNewCondition) { - mpConditions->insert(mpConditions->begin(), pNewCondition); + mpConditions->insert(mpConditions->end(), pNewCondition); } /** Returns the Condition::Pointer corresponding to it's identifier */ @@ -732,7 +732,7 @@ class Mesh : public DataValueContainer, public Flags */ void AddMasterSlaveConstraint(typename MasterSlaveConstraintType::Pointer pNewMasterSlaveConstraint) { - mpMasterSlaveConstraints->insert(mpMasterSlaveConstraints->begin(), pNewMasterSlaveConstraint); + mpMasterSlaveConstraints->insert(mpMasterSlaveConstraints->end(), pNewMasterSlaveConstraint); } /** Returns the MasterSlaveConstraint::Pointer corresponding to it's identifier */ From b3a9a76b6dbf0eabd9dfb2c19aaf674a15ebb8ae Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Tue, 20 Feb 2024 00:16:51 +0100 Subject: [PATCH 07/26] revert elimination builder and solver changes --- ...tion_builder_and_solver_with_constraints.h | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/kratos/solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver_with_constraints.h b/kratos/solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver_with_constraints.h index de9a9e1fdfd4..f4e45f848f4a 100644 --- a/kratos/solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver_with_constraints.h +++ b/kratos/solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver_with_constraints.h @@ -554,8 +554,8 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints if (BaseType::mCalculateReactionsFlag) { for (auto& r_dof : BaseType::mDofSet) { - const bool is_master_fixed = mDoFMasterFixedSet.find(&r_dof) == mDoFMasterFixedSet.end() ? false : true; - const bool is_slave = mDoFSlaveSet.find(&r_dof) == mDoFSlaveSet.end() ? false : true; + const bool is_master_fixed = mDoFMasterFixedSet.find(r_dof) == mDoFMasterFixedSet.end() ? false : true; + const bool is_slave = mDoFSlaveSet.find(r_dof) == mDoFSlaveSet.end() ? false : true; if (is_master_fixed || is_slave) { // Fixed or MPC dof const IndexType equation_id = r_dof.EquationId(); r_reactions_vector[mReactionEquationIdMap[equation_id]] += rb[equation_id]; @@ -741,7 +741,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints aux_dof_set.reserve(mDoFToSolveSystemSize); for (auto& r_dof : BaseType::mDofSet) { if (r_dof.EquationId() < BaseType::mEquationSystemSize) { - auto it = mDoFSlaveSet.find(&r_dof); + auto it = mDoFSlaveSet.find(r_dof); if (it == mDoFSlaveSet.end()) aux_dof_set.push_back( &r_dof ); } @@ -966,7 +966,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints for (auto& dof : BaseType::mDofSet) { if (dof.EquationId() < BaseType::mEquationSystemSize) { const IndexType equation_id = dof.EquationId(); - auto it = mDoFSlaveSet.find(&dof); + auto it = mDoFSlaveSet.find(dof); if (it == mDoFSlaveSet.end()) { solvable_dof_reorder.insert(IndexIndexPairType(equation_id, counter)); master_indices.insert(IndexIndexSetPairType(equation_id, IndexSetType({counter}))); @@ -1318,7 +1318,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints // Updating variables for (auto& r_dof : BaseType::mDofSet) { - if ((r_dof.IsFixed()) || mDoFSlaveSet.find(&r_dof) != mDoFSlaveSet.end()) { + if ((r_dof.IsFixed()) || mDoFSlaveSet.find(r_dof) != mDoFSlaveSet.end()) { r_dof.GetSolutionStepReactionValue() = -r_reactions_vector[mReactionEquationIdMap[r_dof.EquationId()]]; } } @@ -1356,11 +1356,11 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints auto it_dof = it_dof_begin + i; const IndexType equation_id = it_dof->EquationId(); if (equation_id < BaseType::mEquationSystemSize ) { - auto it_first_check = mDoFSlaveSet.find(&*it_dof); + auto it_first_check = mDoFSlaveSet.find(*it_dof); if (it_first_check == mDoFSlaveSet.end()) { - auto it_second_check = mDoFSlaveSet.find(&*it_dof); + auto it_second_check = mDoFSlaveSet.find(*it_dof); if (it_second_check == mDoFSlaveSet.end()) { - if(mDoFMasterFixedSet.find(&*it_dof) == mDoFMasterFixedSet.end()) { + if(mDoFMasterFixedSet.find(*it_dof) == mDoFMasterFixedSet.end()) { scaling_factors[counter] = 1.0; } } @@ -1564,7 +1564,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints for (auto& dof : BaseType::mDofSet) { if (dof.IsFixed()) { - auto it = mDoFMasterFixedSet.find(&dof); + auto it = mDoFMasterFixedSet.find(dof); if (it == mDoFMasterFixedSet.end()) { dof.SetEquationId(--fix_id); } else { @@ -1581,7 +1581,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints IndexType counter = 0; for (auto& dof : BaseType::mDofSet) { if (dof.EquationId() < BaseType::mEquationSystemSize) { - auto it = mDoFSlaveSet.find(&dof); + auto it = mDoFSlaveSet.find(dof); if (it == mDoFSlaveSet.end()) { ++counter; } @@ -1594,8 +1594,8 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints // Finally we build the relation between the EquationID and the component of the reaction counter = 0; for (auto& r_dof : BaseType::mDofSet) { - const bool is_master_fixed = mDoFMasterFixedSet.find(&r_dof) == mDoFMasterFixedSet.end() ? false : true; - const bool is_slave = mDoFSlaveSet.find(&r_dof) == mDoFSlaveSet.end() ? false : true; + const bool is_master_fixed = mDoFMasterFixedSet.find(r_dof) == mDoFMasterFixedSet.end() ? false : true; + const bool is_slave = mDoFSlaveSet.find(r_dof) == mDoFSlaveSet.end() ? false : true; if (is_master_fixed || is_slave) { // Fixed or MPC dof mReactionEquationIdMap.insert({r_dof.EquationId(), counter}); ++counter; @@ -1660,7 +1660,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints auto it_dof = it_dof_begin + i; const IndexType equation_id = it_dof->EquationId(); if (equation_id < BaseType::mEquationSystemSize ) { - auto it = mDoFSlaveSet.find(&*it_dof); + auto it = mDoFSlaveSet.find(*it_dof); if (it == mDoFSlaveSet.end()) { current_solution[counter] = it_dof->GetSolutionStepValue() + rDxSolved[counter]; counter += 1; @@ -1936,8 +1936,8 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints const IndexType i_global = rEquationId[i_local]; auto it_dof = BaseType::mDofSet.begin() + i_global; - const bool is_master_fixed = mDoFMasterFixedSet.find(&*it_dof) == mDoFMasterFixedSet.end() ? false : true; - const bool is_slave = mDoFSlaveSet.find(&*it_dof) == mDoFSlaveSet.end() ? false : true; + const bool is_master_fixed = mDoFMasterFixedSet.find(*it_dof) == mDoFMasterFixedSet.end() ? false : true; + const bool is_slave = mDoFSlaveSet.find(*it_dof) == mDoFSlaveSet.end() ? false : true; if (is_master_fixed || is_slave) { // Fixed or MPC dof double& r_b_value = r_reactions_vector[mReactionEquationIdMap[i_global]]; const double rhs_value = rRHSContribution[i_local]; @@ -1974,7 +1974,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints for (auto& dof : BaseType::mDofSet) { if (dof.EquationId() < BaseType::mEquationSystemSize) { const IndexType equation_id = dof.EquationId(); - auto it = mDoFSlaveSet.find(&dof); + auto it = mDoFSlaveSet.find(dof); if (it == mDoFSlaveSet.end()) { solvable_dof_reorder.insert(IndexIndexPairType(equation_id, counter)); ++counter; @@ -2014,9 +2014,9 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints IndexPartition(mDoFToSolveSystemSize).for_each([&, this](std::size_t Index){ auto it_dof = it_dof_begin + Index; if (Index < this->mEquationSystemSize) { - auto it = mDoFSlaveSet.find(&*it_dof); + auto it = mDoFSlaveSet.find(*it_dof); if (it == mDoFSlaveSet.end()) { - if(mDoFMasterFixedSet.find(&*it_dof) != mDoFMasterFixedSet.end()) { + if(mDoFMasterFixedSet.find(*it_dof) != mDoFMasterFixedSet.end()) { rb[Index] = 0.0; } } @@ -2064,7 +2064,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints for (auto& dof : BaseType::mDofSet) { if (dof.EquationId() < BaseType::mEquationSystemSize) { const IndexType equation_id = dof.EquationId(); - auto it = mDoFSlaveSet.find(&dof); + auto it = mDoFSlaveSet.find(dof); if (it == mDoFSlaveSet.end()) { solvable_dof_reorder.insert(IndexIndexPairType(equation_id, counter)); ++counter; @@ -2192,7 +2192,7 @@ class ResidualBasedEliminationBuilderAndSolverWithConstraints const IndexType equation_id = it_dof->EquationId(); if (equation_id < BaseType::mEquationSystemSize ) { - auto it = mDoFSlaveSet.find(&*it_dof); + auto it = mDoFSlaveSet.find(*it_dof); if (it == mDoFSlaveSet.end()) { u_bar[counter] = it_dof->GetSolutionStepValue() + rDxSolved[counter]; counter += 1; From b0ef86b44f2e59c20fdb50f7bb73cb8c734f4c2b Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Tue, 20 Feb 2024 00:17:13 +0100 Subject: [PATCH 08/26] change dofarraytype --- kratos/elements/distance_calculation_element_simplex.h | 2 +- kratos/includes/condition.h | 3 ++- kratos/includes/element.h | 3 ++- kratos/includes/model_part.h | 3 ++- kratos/utilities/dof_updater.h | 5 +++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/kratos/elements/distance_calculation_element_simplex.h b/kratos/elements/distance_calculation_element_simplex.h index ad3661648c50..31137b5c0df2 100644 --- a/kratos/elements/distance_calculation_element_simplex.h +++ b/kratos/elements/distance_calculation_element_simplex.h @@ -98,7 +98,7 @@ class DistanceCalculationElementSimplex : public Element typedef std::vector DofsVectorType; - typedef PointerVectorSet DofsArrayType; + typedef Element::DofsArrayType DofsArrayType; /// Type for shape function values container typedef Kratos::Vector ShapeFunctionsType; diff --git a/kratos/includes/condition.h b/kratos/includes/condition.h index 404f4c42f6dd..efd59dba7a93 100644 --- a/kratos/includes/condition.h +++ b/kratos/includes/condition.h @@ -23,6 +23,7 @@ #include "includes/geometrical_object.h" #include "includes/kratos_parameters.h" #include "containers/global_pointers_vector.h" +#include "containers/set_identity_function.h" namespace Kratos { @@ -99,7 +100,7 @@ class Condition : public GeometricalObject typedef std::vector DofsVectorType; - typedef PointerVectorSet DofsArrayType; + typedef PointerVectorSet> DofsArrayType; ///Type definition for integration methods typedef GeometryData::IntegrationMethod IntegrationMethod; diff --git a/kratos/includes/element.h b/kratos/includes/element.h index 563a5e76bfd3..1b4f36cddb83 100644 --- a/kratos/includes/element.h +++ b/kratos/includes/element.h @@ -24,6 +24,7 @@ #include "includes/constitutive_law.h" #include "includes/kratos_parameters.h" #include "containers/global_pointers_vector.h" +#include "containers/set_identity_function.h" namespace Kratos { @@ -99,7 +100,7 @@ class Element : public GeometricalObject typedef std::vector DofsVectorType; - typedef PointerVectorSet DofsArrayType; + typedef PointerVectorSet> DofsArrayType; ///Type definition for integration methods typedef GeometryData::IntegrationMethod IntegrationMethod; diff --git a/kratos/includes/model_part.h b/kratos/includes/model_part.h index e68377a179a7..f4e77f8f6777 100644 --- a/kratos/includes/model_part.h +++ b/kratos/includes/model_part.h @@ -39,6 +39,7 @@ #include "includes/master_slave_constraint.h" #include "containers/variable.h" #include "containers/variable_data.h" +#include "containers/set_identity_function.h" namespace Kratos { @@ -112,7 +113,7 @@ class KRATOS_API(KRATOS_CORE) ModelPart final typedef Matrix MatrixType; typedef Vector VectorType; - typedef PointerVectorSet DofsArrayType; + typedef PointerVectorSet> DofsArrayType; typedef Node NodeType; typedef Geometry GeometryType; diff --git a/kratos/utilities/dof_updater.h b/kratos/utilities/dof_updater.h index f621b2b22c61..a0e301d89661 100644 --- a/kratos/utilities/dof_updater.h +++ b/kratos/utilities/dof_updater.h @@ -45,8 +45,9 @@ class DofUpdater /// Pointer definition of DofUpdater KRATOS_CLASS_POINTER_DEFINITION(DofUpdater); - using DofType = Dof; - using DofsArrayType = PointerVectorSet; + using DofType = ModelPart::DofType; + + using DofsArrayType = ModelPart::DofsArrayType; using SystemVectorType = typename TSparseSpace::VectorType; From f5a7f0540d6dfd9ddc0f6d2555c4789288d367e3 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Tue, 20 Feb 2024 00:29:41 +0100 Subject: [PATCH 09/26] fix ranged insert bug with end --- kratos/containers/pointer_vector_set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index 329d6a665025..79c670ce87b1 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -661,7 +661,7 @@ class PointerVectorSet final for (; first != new_last; ++first) { // find the lower bound element. p_current_itr = std::lower_bound(p_current_itr, mData.end(), KeyOf(**first), CompareKey()); - if (!EqualKeyTo(KeyOf(**first))(*p_current_itr)) { + if (p_current_itr == mData.end() || !EqualKeyTo(KeyOf(**first))(*p_current_itr)) { p_current_itr = mData.insert(p_current_itr, *first); } } From 8dfbe0964dfb12f1b8f95a8bdc306153f9a1b153 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Tue, 20 Feb 2024 12:02:48 +0100 Subject: [PATCH 10/26] fix mmg reordering --- .../custom_processes/mmg/mmg_process.cpp | 10 +++++++--- .../custom_utilities/mmg/mmg_utilities.cpp | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/applications/MeshingApplication/custom_processes/mmg/mmg_process.cpp b/applications/MeshingApplication/custom_processes/mmg/mmg_process.cpp index cd711e2c8493..f9f7caf819cd 100755 --- a/applications/MeshingApplication/custom_processes/mmg/mmg_process.cpp +++ b/applications/MeshingApplication/custom_processes/mmg/mmg_process.cpp @@ -32,7 +32,7 @@ /* The mappers includes */ #include "spaces/ublas_space.h" #include "mappers/mapper_flags.h" -#include "factories/mapper_factory.h" +#include "factories/mapper_factory.h" // NOTE: The following contains the license of the MMG library /* ============================================================================= @@ -366,6 +366,10 @@ void MmgProcess::InitializeMeshData() for (auto it_dof = mDofs.begin(); it_dof != mDofs.end(); ++it_dof) (**it_dof).FreeDof(); + mrThisModelPart.Nodes().Unique(); + mrThisModelPart.Conditions().Unique(); + mrThisModelPart.Elements().Unique(); + // Generate the maps of reference mMmgUtilities.GenerateReferenceMaps(mrThisModelPart, aux_ref_cond, aux_ref_elem, mpRefCondition, mpRefElement); @@ -590,7 +594,7 @@ void MmgProcess::ExecuteRemeshing() ModelPart& r_old_auxiliar_model_part = r_old_model_part.GetSubModelPart("AUXILIAR_COLLAPSED_PRISMS"); ModelPart& r_auxiliary_model_part = mrThisModelPart.GetSubModelPart("AUXILIAR_COLLAPSED_PRISMS"); - // Define mapper factory + // Define mapper factory DEFINE_MAPPER_FACTORY_SERIAL if (MapperFactoryType::HasMapper("nearest_element") && mThisParameters["use_mapper_if_available"].GetBool()) { KRATOS_INFO_IF("MmgProcess", mEchoLevel > 0) << "Using MappingApplication to interpolate values" << std::endl; @@ -1501,7 +1505,7 @@ const Parameters MmgProcess::GetDefaultParameters() const "max_num_search_iterations" : 8, "echo_level" : 0 } - }, + }, "extrapolate_contour_values" : true, "surface_elements" : false, "search_parameters" : { diff --git a/applications/MeshingApplication/custom_utilities/mmg/mmg_utilities.cpp b/applications/MeshingApplication/custom_utilities/mmg/mmg_utilities.cpp index d35f93d669ea..54274ffbd38f 100644 --- a/applications/MeshingApplication/custom_utilities/mmg/mmg_utilities.cpp +++ b/applications/MeshingApplication/custom_utilities/mmg/mmg_utilities.cpp @@ -2854,7 +2854,7 @@ void MmgUtilities::SetLocalParameter( double HMin, double HMax, double HausdorffValue - ) + ) { if ( MMG2D_Set_localParameter(mMmgMesh, mMmgMet, MMG5_Edg, rColor, HMin, HMax, HausdorffValue) != 1) KRATOS_ERROR << "Unable to set local parameter" << std::endl; @@ -2869,7 +2869,7 @@ void MmgUtilities::SetLocalParameter( double HMin, double HMax, double HausdorffValue - ) + ) { if ( MMG3D_Set_localParameter(mMmgMesh, mMmgMet, MMG5_Triangle, rColor, HMin, HMax, HausdorffValue) != 1) KRATOS_ERROR << "Unable to set local parameter" << std::endl; @@ -2884,7 +2884,7 @@ void MmgUtilities::SetLocalParameter( double HMin, double HMax, double HausdorffValue - ) + ) { if ( MMGS_Set_localParameter(mMmgMesh, mMmgMet, MMG5_Triangle, rColor, HMin, HMax, HausdorffValue) != 1) KRATOS_ERROR << "Unable to set local parameter" << std::endl; @@ -3578,6 +3578,10 @@ void MmgUtilities::ReorderAllIds(ModelPart& rModelPart) for(IndexType i = 0; i < r_elements_array.size(); ++i) (it_elem_begin + i)->SetId(i + 1); + r_nodes_array.Unique(); + r_conditions_array.Unique(); + r_elements_array.Unique(); + KRATOS_CATCH(""); } @@ -3801,6 +3805,8 @@ void MmgUtilities::GenerateMeshDataFromModelPart( } } + r_nodes_array.Unique(); + /* Conditions */ counter_to_remesh = block_for_each>( r_conditions_array, @@ -3829,6 +3835,8 @@ void MmgUtilities::GenerateMeshDataFromModelPart( } } + r_conditions_array.Unique(); + /* Elements */ counter_to_remesh = block_for_each>( r_elements_array, @@ -3857,6 +3865,8 @@ void MmgUtilities::GenerateMeshDataFromModelPart( } } + r_elements_array.Unique(); + // Now we compute the colors rColors.clear(); ColorsMapType nodes_colors, cond_colors, elem_colors; From f2f3dcca27ddbaad2e73a9ab9fe9464edab0a079 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Tue, 20 Feb 2024 13:30:14 +0100 Subject: [PATCH 11/26] fix dof updater --- kratos/utilities/dof_updater.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kratos/utilities/dof_updater.h b/kratos/utilities/dof_updater.h index a0e301d89661..f3923712550a 100644 --- a/kratos/utilities/dof_updater.h +++ b/kratos/utilities/dof_updater.h @@ -17,6 +17,7 @@ #include "includes/define.h" #include "includes/model_part.h" #include "utilities/parallel_utilities.h" +#include "containers/set_identity_function.h" namespace Kratos { @@ -45,9 +46,8 @@ class DofUpdater /// Pointer definition of DofUpdater KRATOS_CLASS_POINTER_DEFINITION(DofUpdater); - using DofType = ModelPart::DofType; - - using DofsArrayType = ModelPart::DofsArrayType; + using DofType = Dof; + using DofsArrayType = PointerVectorSet>; using SystemVectorType = typename TSparseSpace::VectorType; From 1c9af8ea4ab6181595b6d2951aa523d9851f7cce Mon Sep 17 00:00:00 2001 From: Suneth Warnakulasuriya Date: Tue, 20 Feb 2024 15:58:23 +0100 Subject: [PATCH 12/26] add additional reserve --- kratos/containers/pointer_vector_set.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index 79c670ce87b1..a8d132672fa7 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -652,6 +652,7 @@ class PointerVectorSet final auto new_last = std::unique(first, last, EqualKeyTo()); if (empty()) { + mData.reserve(std::distance(first, new_last)); for (; first != new_last; ++first) { mData.push_back(*first); } From d0ef0e7ad8a02a6cbf6e8a823d973759301e9dc9 Mon Sep 17 00:00:00 2001 From: Suneth Warnakulasuriya Date: Tue, 20 Feb 2024 16:31:42 +0100 Subject: [PATCH 13/26] add another insertion method --- kratos/containers/pointer_vector_set.h | 35 ++++++++++- .../containers/test_pointer_vector_set.cpp | 59 +++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index a8d132672fa7..cac0568be29f 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -652,7 +652,7 @@ class PointerVectorSet final auto new_last = std::unique(first, last, EqualKeyTo()); if (empty()) { - mData.reserve(std::distance(first, new_last)); + mData.reserve(std::distance(first, new_last)); for (; first != new_last; ++first) { mData.push_back(*first); } @@ -674,6 +674,39 @@ class PointerVectorSet final mSortedPartSize = mData.size(); } + /** + * @brief Insert elements from another PointerVectorSet. + * @details This function inserts element pointers from another PointerVectorSet into the current set. + * Since, PointerVectorSet is assumed to be sorted and unique, the incoming PointerVectorSet is not + * sorted and made unique again. This will not insert any elements in the incoming set, if there exists an element with a key + * which is equal to an element's key in the input range. + * @param rOther Other PointerVectorSet to insert elements from. + */ + void insert(const PointerVectorSet& rOther) + { + if (empty()) { + mData.reserve(rOther.mData.size()); + for (auto& p_element : rOther.mData) { + mData.push_back(p_element); + } + } else { + auto p_current_itr = mData.begin(); + // now add the new elements + for (auto& p_element : rOther.mData) { + // find the lower bound element. + p_current_itr = std::lower_bound(p_current_itr, mData.end(), KeyOf(*p_element), CompareKey()); + if (p_current_itr == mData.end() || !EqualKeyTo(KeyOf(*p_element))(*p_current_itr)) { + p_current_itr = mData.insert(p_current_itr, p_element); + } + } + } + + // TODO: To be removed once push back is removed. + // insert assumes the PointerVectorSet is already sorted, + // hence mSortedPartSize should be mData.size() + mSortedPartSize = mData.size(); + } + /** * @brief Erase an element at the specified position. * @details This function erases the element at the specified position and updates `mSortedPartSize` diff --git a/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp b/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp index 9ad5a8f0d8c4..77f2763ed11d 100644 --- a/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp +++ b/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp @@ -254,6 +254,65 @@ KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert6, KratosCoreFastSuite) KRATOS_EXPECT_EQ(&*(itr++), &*p_element_8); } +KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert7, KratosCoreFastSuite) +{ + PointerVectorSet test_container_1, test_container_2, test_container_3; + auto p_element_1 = Kratos::make_intrusive(1); + auto p_element_2 = Kratos::make_intrusive(2); + auto p_element_3 = Kratos::make_intrusive(3); + auto p_element_4 = Kratos::make_intrusive(4); + auto p_element_5 = Kratos::make_intrusive(5); + auto p_element_6 = Kratos::make_intrusive(6); + auto p_element_7 = Kratos::make_intrusive(7); + auto p_element_8 = Kratos::make_intrusive(8); + auto p_element_3_copy = Kratos::make_intrusive(3); + + std::vector tmp; + tmp.push_back(p_element_2); + tmp.push_back(p_element_1); + tmp.push_back(p_element_5); + tmp.push_back(p_element_8); + + test_container_1.insert(tmp.begin(), tmp.end()); + KRATOS_EXPECT_EQ(test_container_1.size(), 4); + auto itr = test_container_1.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_1); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_2); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_5); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_8); + + test_container_2.insert(test_container_1); + KRATOS_EXPECT_EQ(test_container_2.size(), 4); + itr = test_container_2.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_1); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_2); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_5); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_8); + + tmp.clear(); + tmp.push_back(p_element_3); + tmp.push_back(p_element_4); + tmp.push_back(p_element_5); + tmp.push_back(p_element_3); + tmp.push_back(p_element_3_copy); + tmp.push_back(p_element_1); + tmp.push_back(p_element_7); + tmp.push_back(p_element_6); + test_container_3.insert(tmp.begin(), tmp.end()); + + test_container_2.insert(test_container_3); + KRATOS_EXPECT_EQ(test_container_2.size(), 8); + itr = test_container_2.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_1); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_2); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_3); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_4); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_5); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_6); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_7); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_8); +} + KRATOS_TEST_CASE_IN_SUITE(TestPointerVectorSet, KratosCoreFastSuite) { // create model and model part From 9c00f71791bbdef8cd92bbaa188ab3fcf92d0fa8 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Fri, 23 Feb 2024 00:41:29 +0100 Subject: [PATCH 14/26] introduce set function --- .../set_address_identity_function.h | 70 ----------- kratos/containers/set_function.h | 115 ++++++++++++++++++ 2 files changed, 115 insertions(+), 70 deletions(-) delete mode 100644 kratos/containers/set_address_identity_function.h create mode 100644 kratos/containers/set_function.h diff --git a/kratos/containers/set_address_identity_function.h b/kratos/containers/set_address_identity_function.h deleted file mode 100644 index 532b7f0bcab9..000000000000 --- a/kratos/containers/set_address_identity_function.h +++ /dev/null @@ -1,70 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Pooyan Dadvand -// Suneth Warnakulasuriya -// -// - -#pragma once - -// System includes -#include - -// External includes - -// Project includes - -namespace Kratos -{ -///@name Kratos Classes -///@{ - -/** - * @class SetAddressIdentityFunction - * @brief A functor that serves as the identity function for memory locations. - * @details This class provides two overloaded operator() functions, one for non-const objects - * and another for const objects. The operator() returns the input objects memory location as it is, - * effectively acting as an identity function for address. - * The purpose of this functor is to allow objects' memory locations to be used as keys in sets or other - * containers that require comparison. By using this functor, you can avoid defining - * custom comparison functions or operators when the object itself can be considered - * for comparison. - * @tparam TDataType The data type of the object that the functor operates on. - * @author Pooyan Dadvand - * @author Suneth Warnakulasuriya - */ -template -class SetAddressIdentityFunction -{ -public: - /** - * @brief Operator that returns a non-const reference pointer to the input object. - * @param data The input object of type TDataType. - * @return A non-const reference pointer to the same object as provided in the parameter. - */ - TDataType* operator()(TDataType& data) - { - return &data; - } - - /** - * @brief Operator that returns a const reference pointer to the input object. - * @param data The input object of type TDataType. - * @return A const reference pointer to the same object as provided in the parameter. - */ - TDataType const * operator()(const TDataType& data) const - { - return &data; - } -}; - -///@} - -} // namespace Kratos. diff --git a/kratos/containers/set_function.h b/kratos/containers/set_function.h new file mode 100644 index 000000000000..ae1c9b58a17f --- /dev/null +++ b/kratos/containers/set_function.h @@ -0,0 +1,115 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Suneth Warnakulasuriya +// + +#pragma once + +// System includes +#include +#include +#include + +// External includes + +// Project includes + +namespace Kratos +{ +///@name Kratos Classes +///@{ + +/** + * @class TestOperators + * @brief Operator class to test whether operators "<" and "==" is defined for given TDataType. + */ +struct TestOperators +{ + template + static auto TestEqual(TDataType*) -> decltype(std::declval() == std::declval()); + template + static auto TestEqual(...) -> std::false_type; + + template + static auto TestLess(TDataType*) -> decltype(std::declval() < std::declval()); + template + static auto TestLess(...) -> std::false_type; +}; + +/** + * @class SetFunction + * @brief A functor that serves as the identity function if "<" and "==" operators are defined, otherwise, returns memory location. + * @details This class provides two overloaded operator() functions, one for non-const objects + * and another for const objects. The operator() returns the input objects memory location as it is, + * effectively acting as an identity function for address if the operators "<" and "==" is not defined. Otherwise, + * this returns the exact input object. + * + * The purpose of this functor is to allow objects' memory locations or exact object to be used as keys in sets or other + * containers that require comparison. By using this functor, you can avoid defining + * custom comparison functions or operators when the object itself can be considered + * for comparison. + * @tparam TDataType The data type of the object that the functor operates on. + * @author Suneth Warnakulasuriya + */ +template +class SetFunction +{ +private: + ///@name Private static variables + ///@{ + + static constexpr bool HasOperatorEqual = std::is_same_v(0))>; + + static constexpr bool HasOperatorLess = std::is_same_v(0))>; + + static constexpr bool HasOperatorsDefined = HasOperatorEqual && HasOperatorLess; + + ///@} + +public: + ///@name Public operators + ///@{ + + /** + * @brief Operator that returns a non-const reference pointer to the input object if "<" and "==" operators are defined. + * Otherwise this returns a reference to the input object. + * @param data The input object of type TDataType. + * @return A non-const reference pointer or reference to the same object as provided in the parameter. + */ + std::conditional_t operator()(TDataType& rData) + { + if constexpr(HasOperatorsDefined) { + return rData; + } else { + return &rData; + } + } + + /** + * @brief Operator that returns a const reference pointer to the input object if "<" and "==" operators are defined. + * Otherwise this returns the const reference to the input object. + * @param data The input object of type TDataType. + * @return A const reference pointer or reference to the same object as provided in the parameter. + */ + std::conditional_t operator()(const TDataType& rData) const + { + if constexpr(HasOperatorsDefined) { + return rData; + } else { + return &rData; + } + } + + ///@} +}; + +///@} + +} // namespace Kratos. From 8b04cec3867f6548581b9413689f347fc0d429c4 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Fri, 23 Feb 2024 00:51:51 +0100 Subject: [PATCH 15/26] define IndexedObject operators --- kratos/includes/indexed_object.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kratos/includes/indexed_object.h b/kratos/includes/indexed_object.h index 47ec06857142..2ff6cbf2d9e5 100644 --- a/kratos/includes/indexed_object.h +++ b/kratos/includes/indexed_object.h @@ -260,6 +260,21 @@ inline std::ostream& operator << (std::ostream& rOStream, return rOStream; } + +inline bool operator<( + const IndexedObject& rFirst, + const IndexedObject& rSecond) +{ + return rFirst.Id() < rSecond.Id(); +} + +inline bool operator==( + const IndexedObject& rFirst, + const IndexedObject& rSecond) +{ + return rFirst.Id() == rSecond.Id(); +} + ///@} } // namespace Kratos. From e86088b296af5815e4ab0648a152cef48f68a2ba Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Fri, 23 Feb 2024 00:52:08 +0100 Subject: [PATCH 16/26] use set function in PointerVectorSet --- kratos/containers/pointer_vector_set.h | 4 ++-- kratos/elements/distance_calculation_element_simplex.h | 2 +- kratos/includes/condition.h | 3 +-- kratos/includes/element.h | 3 +-- kratos/includes/model_part.h | 3 +-- kratos/utilities/dof_updater.h | 3 +-- 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index cac0568be29f..60bb400a595c 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -27,7 +27,7 @@ // Project includes #include "includes/define.h" #include "includes/serializer.h" -#include "containers/set_address_identity_function.h" +#include "containers/set_function.h" namespace Kratos { @@ -63,7 +63,7 @@ namespace Kratos * @author Pooyan Dadvand */ template, + class TGetKeyType = SetFunction, class TCompareType = std::less()(std::declval()))>, class TEqualType = std::equal_to()(std::declval()))>, class TPointerType = typename TDataType::Pointer, diff --git a/kratos/elements/distance_calculation_element_simplex.h b/kratos/elements/distance_calculation_element_simplex.h index 31137b5c0df2..ad3661648c50 100644 --- a/kratos/elements/distance_calculation_element_simplex.h +++ b/kratos/elements/distance_calculation_element_simplex.h @@ -98,7 +98,7 @@ class DistanceCalculationElementSimplex : public Element typedef std::vector DofsVectorType; - typedef Element::DofsArrayType DofsArrayType; + typedef PointerVectorSet DofsArrayType; /// Type for shape function values container typedef Kratos::Vector ShapeFunctionsType; diff --git a/kratos/includes/condition.h b/kratos/includes/condition.h index efd59dba7a93..404f4c42f6dd 100644 --- a/kratos/includes/condition.h +++ b/kratos/includes/condition.h @@ -23,7 +23,6 @@ #include "includes/geometrical_object.h" #include "includes/kratos_parameters.h" #include "containers/global_pointers_vector.h" -#include "containers/set_identity_function.h" namespace Kratos { @@ -100,7 +99,7 @@ class Condition : public GeometricalObject typedef std::vector DofsVectorType; - typedef PointerVectorSet> DofsArrayType; + typedef PointerVectorSet DofsArrayType; ///Type definition for integration methods typedef GeometryData::IntegrationMethod IntegrationMethod; diff --git a/kratos/includes/element.h b/kratos/includes/element.h index 1b4f36cddb83..563a5e76bfd3 100644 --- a/kratos/includes/element.h +++ b/kratos/includes/element.h @@ -24,7 +24,6 @@ #include "includes/constitutive_law.h" #include "includes/kratos_parameters.h" #include "containers/global_pointers_vector.h" -#include "containers/set_identity_function.h" namespace Kratos { @@ -100,7 +99,7 @@ class Element : public GeometricalObject typedef std::vector DofsVectorType; - typedef PointerVectorSet> DofsArrayType; + typedef PointerVectorSet DofsArrayType; ///Type definition for integration methods typedef GeometryData::IntegrationMethod IntegrationMethod; diff --git a/kratos/includes/model_part.h b/kratos/includes/model_part.h index f4e77f8f6777..e68377a179a7 100644 --- a/kratos/includes/model_part.h +++ b/kratos/includes/model_part.h @@ -39,7 +39,6 @@ #include "includes/master_slave_constraint.h" #include "containers/variable.h" #include "containers/variable_data.h" -#include "containers/set_identity_function.h" namespace Kratos { @@ -113,7 +112,7 @@ class KRATOS_API(KRATOS_CORE) ModelPart final typedef Matrix MatrixType; typedef Vector VectorType; - typedef PointerVectorSet> DofsArrayType; + typedef PointerVectorSet DofsArrayType; typedef Node NodeType; typedef Geometry GeometryType; diff --git a/kratos/utilities/dof_updater.h b/kratos/utilities/dof_updater.h index f3923712550a..f621b2b22c61 100644 --- a/kratos/utilities/dof_updater.h +++ b/kratos/utilities/dof_updater.h @@ -17,7 +17,6 @@ #include "includes/define.h" #include "includes/model_part.h" #include "utilities/parallel_utilities.h" -#include "containers/set_identity_function.h" namespace Kratos { @@ -47,7 +46,7 @@ class DofUpdater KRATOS_CLASS_POINTER_DEFINITION(DofUpdater); using DofType = Dof; - using DofsArrayType = PointerVectorSet>; + using DofsArrayType = PointerVectorSet; using SystemVectorType = typename TSparseSpace::VectorType; From 5760f73492b81c984a3e056debee878ee36a101f Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Fri, 23 Feb 2024 09:08:43 +0100 Subject: [PATCH 17/26] add operator== to closest_point --- .../MappingApplication/custom_utilities/closest_points.cpp | 5 +++++ .../MappingApplication/custom_utilities/closest_points.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/applications/MappingApplication/custom_utilities/closest_points.cpp b/applications/MappingApplication/custom_utilities/closest_points.cpp index 5057ce2dbbe9..1957a498c04f 100644 --- a/applications/MappingApplication/custom_utilities/closest_points.cpp +++ b/applications/MappingApplication/custom_utilities/closest_points.cpp @@ -36,6 +36,11 @@ bool PointWithId::operator<(const PointWithId& rOther) const return mDistance < rOther.mDistance; } +bool PointWithId::operator==(const PointWithId& rOther) const +{ + return Point::operator==(rOther); +} + void PointWithId::save(Serializer &rSerializer) const { KRATOS_SERIALIZE_SAVE_BASE_CLASS(rSerializer, IndexedObject); diff --git a/applications/MappingApplication/custom_utilities/closest_points.h b/applications/MappingApplication/custom_utilities/closest_points.h index 94638e73e638..a2d092490ce9 100644 --- a/applications/MappingApplication/custom_utilities/closest_points.h +++ b/applications/MappingApplication/custom_utilities/closest_points.h @@ -44,6 +44,8 @@ class KRATOS_API(MAPPING_APPLICATION) PointWithId : public IndexedObject, public bool operator<(const PointWithId& rOther) const; + bool operator==(const PointWithId& rOther) const; + double GetDistance() const { return mDistance; } private: From 6e7a68f4f889b6c1a71d66874718fbe544efb6e4 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Mon, 26 Feb 2024 23:44:16 +0100 Subject: [PATCH 18/26] use cbegin() --- kratos/containers/pointer_vector_set.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index 60bb400a595c..2195f9a9a584 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -613,11 +613,11 @@ class PointerVectorSet final // given position is invalid. Hence, discarding the hint. return insert(value); } - } else if (EqualKeyTo(KeyOf(*position_hint))(*ptr_begin())) { + } else if (position_hint == cbegin()) { // trying to insert at the front. if (KeyOf(*value) < KeyOf(*position_hint)) { // key at the position hint is greater than the value of key. Hence position hint - // is valid. So using the push back. + // is valid. So using insertion at the beginning. mSortedPartSize = mData.size() + 1; return mData.insert(mData.begin(), value); } else { From f6046176c5723dbd36cd8cd32035c83c2a143bdf Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Tue, 27 Feb 2024 13:02:01 +0100 Subject: [PATCH 19/26] add additional insert mechanism and test --- kratos/containers/pointer_vector_set.h | 112 +++++++++++------- .../containers/test_pointer_vector_set.cpp | 112 +++++++++++++++++- 2 files changed, 174 insertions(+), 50 deletions(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index 2195f9a9a584..b7bdfa9e2f61 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -650,61 +650,26 @@ class PointerVectorSet final // first sorts the input iterators and make the input unique. std::sort(first, last, CompareKey()); auto new_last = std::unique(first, last, EqualKeyTo()); - - if (empty()) { - mData.reserve(std::distance(first, new_last)); - for (; first != new_last; ++first) { - mData.push_back(*first); - } - } else { - auto p_current_itr = mData.begin(); - // now add the new elements - for (; first != new_last; ++first) { - // find the lower bound element. - p_current_itr = std::lower_bound(p_current_itr, mData.end(), KeyOf(**first), CompareKey()); - if (p_current_itr == mData.end() || !EqualKeyTo(KeyOf(**first))(*p_current_itr)) { - p_current_itr = mData.insert(p_current_itr, *first); - } - } - } - - // TODO: To be removed once push back is removed. - // insert assumes the PointerVectorSet is already sorted, - // hence mSortedPartSize should be mData.size() - mSortedPartSize = mData.size(); + SortedInsert(first, new_last); } /** - * @brief Insert elements from another PointerVectorSet. - * @details This function inserts element pointers from another PointerVectorSet into the current set. + * @brief Insert elements from another PointerVectorSet range. + * @details This function inserts element pointers from another PointerVectorSet range specified by first and last into the current set. * Since, PointerVectorSet is assumed to be sorted and unique, the incoming PointerVectorSet is not * sorted and made unique again. This will not insert any elements in the incoming set, if there exists an element with a key * which is equal to an element's key in the input range. - * @param rOther Other PointerVectorSet to insert elements from. + * @param first Other PointerVectorSet starting iterator + * @param last Other PointerVectorSet ending iterator */ - void insert(const PointerVectorSet& rOther) + void insert(PointerVectorSet::const_iterator first, PointerVectorSet::const_iterator last) { - if (empty()) { - mData.reserve(rOther.mData.size()); - for (auto& p_element : rOther.mData) { - mData.push_back(p_element); - } - } else { - auto p_current_itr = mData.begin(); - // now add the new elements - for (auto& p_element : rOther.mData) { - // find the lower bound element. - p_current_itr = std::lower_bound(p_current_itr, mData.end(), KeyOf(*p_element), CompareKey()); - if (p_current_itr == mData.end() || !EqualKeyTo(KeyOf(*p_element))(*p_current_itr)) { - p_current_itr = mData.insert(p_current_itr, p_element); - } - } - } + SortedInsert(first, last); + } - // TODO: To be removed once push back is removed. - // insert assumes the PointerVectorSet is already sorted, - // hence mSortedPartSize should be mData.size() - mSortedPartSize = mData.size(); + void insert(const PointerVectorSet& rOther) + { + insert(rOther.begin(), rOther.end()); } /** @@ -1094,6 +1059,61 @@ class PointerVectorSet final ///@name Private Operations ///@{ + template + void SortedInsert(TIteratorType first, TIteratorType last) + { + if (std::distance(first, last) == 0) { + return; + } + + if (empty()) { + mData.reserve(std::distance(first, last)); + for (auto it = first; it != last; ++it) { + mData.push_back(TPointerType(*(it.base()))); + } + } else { + // first find the largest range + const auto lower_bound_first = std::lower_bound(mData.begin(), mData.end(), KeyOf(**(first.base())), CompareKey()); + const auto upper_bound_last = std::upper_bound(lower_bound_first, mData.end(), KeyOf(**((last-1).base())), CompareKey()); + + // then find the compact sub range + const auto upper_bound_first = std::upper_bound(lower_bound_first, upper_bound_last, KeyOf(**(first.base())), CompareKey()); + const auto lower_bound_last = std::lower_bound(lower_bound_first, upper_bound_last, KeyOf(**((last-1).base())), CompareKey()); + + if (lower_bound_first == lower_bound_last && + lower_bound_first == upper_bound_first && + lower_bound_first == upper_bound_last) + { + // all 4 bounds are equal, hence this can be inserted without checking further + if (lower_bound_first == mData.end()) { + for (auto it = first; it != last; ++it) { + mData.push_back(TPointerType(*(it.base()))); + } + } else { + auto current_pos = lower_bound_first - 1; + for (auto it = first; it != last; ++it) { + current_pos = mData.insert(current_pos + 1, TPointerType(*(it.base()))); + } + } + } else { + auto p_current_itr = mData.begin(); + // now add the new elements + for (auto it = first; it != last; ++it) { + // find the lower bound element. + p_current_itr = std::lower_bound(p_current_itr, mData.end(), KeyOf(**(it.base())), CompareKey()); + if (p_current_itr == mData.end() || !EqualKeyTo(KeyOf(**(it.base())))(*p_current_itr)) { + p_current_itr = mData.insert(p_current_itr, TPointerType(*(it.base()))); + } + } + } + } + + // TODO: To be removed once push back is removed. + // insert assumes the PointerVectorSet is already sorted, + // hence mSortedPartSize should be mData.size() + mSortedPartSize = mData.size(); + } + /** * @brief Extract the key from an iterator and apply a key extraction function. * @details This function extracts the key from an iterator and applies a key extraction function of type `TGetKeyType` to it. diff --git a/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp b/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp index 77f2763ed11d..c71b995b16d2 100644 --- a/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp +++ b/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp @@ -30,13 +30,13 @@ namespace Testing { KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetCBeginAndCEnd, KratosCoreFastSuite) { - PointerVectorSet test_container; + PointerVectorSet test_container; auto p_element_1 = Kratos::make_intrusive(1); auto p_element_2 = Kratos::make_intrusive(2); auto p_element_3 = Kratos::make_intrusive(3); - test_container.push_back(p_element_1); - test_container.push_back(p_element_2); - test_container.push_back(p_element_3); + test_container.insert(p_element_1); + test_container.insert(p_element_2); + test_container.insert(p_element_3); KRATOS_EXPECT_EQ(test_container.cbegin()->Id(), 1); KRATOS_EXPECT_EQ((test_container.cend()-1)->Id(), 3); @@ -313,6 +313,110 @@ KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert7, KratosCoreFastSuite) KRATOS_EXPECT_EQ(&*(itr++), &*p_element_8); } +KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert8, KratosCoreFastSuite) +{ + PointerVectorSet test_container_1, test_container_2, test_container_3; + std::vector elements; + for (IndexType i = 0; i < 50; ++i) { + elements.push_back(Kratos::make_intrusive(i + 1)); + } + auto p_element_4_copy = Kratos::make_intrusive(4); + auto p_element_10_copy = Kratos::make_intrusive(10); + + std::vector tmp; + tmp.push_back(elements[2]); + tmp.push_back(elements[1]); + tmp.push_back(elements[25]); + tmp.push_back(elements[28]); + + test_container_1.insert(tmp.begin(), tmp.end()); + KRATOS_EXPECT_EQ(test_container_1.size(), 4); + auto itr = test_container_1.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[1]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[2]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[25]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[28]); + + test_container_2.insert(test_container_1); + KRATOS_EXPECT_EQ(test_container_2.size(), 4); + itr = test_container_2.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[1]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[2]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[25]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[28]); + + tmp.clear(); + tmp.push_back(elements[3]); + tmp.push_back(elements[4]); + tmp.push_back(elements[5]); + tmp.push_back(elements[3]); + tmp.push_back(p_element_4_copy); + tmp.push_back(p_element_10_copy); + tmp.push_back(elements[7]); + tmp.push_back(elements[6]); + test_container_3.insert(tmp.begin(), tmp.end()); + + test_container_2.insert(test_container_3); + KRATOS_EXPECT_EQ(test_container_2.size(), 10); + itr = test_container_2.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[1]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[2]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[3]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[4]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[5]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[6]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[7]); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_10_copy); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[25]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[28]); + + tmp.clear(); + tmp.push_back(elements[39]); + tmp.push_back(elements[29]); + tmp.push_back(elements[48]); + test_container_2.insert(tmp.begin(), tmp.end()); + + KRATOS_EXPECT_EQ(test_container_2.size(), 13); + itr = test_container_2.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[1]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[2]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[3]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[4]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[5]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[6]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[7]); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_10_copy); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[25]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[28]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[29]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[39]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[48]); + + tmp.clear(); + tmp.push_back(elements[28]); + tmp.push_back(elements[31]); + tmp.push_back(elements[45]); + test_container_2.insert(tmp.begin(), tmp.end()); + + KRATOS_EXPECT_EQ(test_container_2.size(), 15); + itr = test_container_2.begin(); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[1]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[2]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[3]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[4]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[5]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[6]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[7]); + KRATOS_EXPECT_EQ(&*(itr++), &*p_element_10_copy); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[25]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[28]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[29]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[31]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[39]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[45]); + KRATOS_EXPECT_EQ(&*(itr++), &*elements[48]); +} + KRATOS_TEST_CASE_IN_SUITE(TestPointerVectorSet, KratosCoreFastSuite) { // create model and model part From 1437a2564ef9b785d1a14e1c2c2cdaecd0060015 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Wed, 6 Mar 2024 12:54:39 +0100 Subject: [PATCH 20/26] remove use of *::base() --- kratos/containers/pointer_vector_set.h | 51 +++++++++++++++++++++----- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index b7bdfa9e2f61..dfc899966c56 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -1069,16 +1069,16 @@ class PointerVectorSet final if (empty()) { mData.reserve(std::distance(first, last)); for (auto it = first; it != last; ++it) { - mData.push_back(TPointerType(*(it.base()))); + mData.push_back(TPointerType(&GetReference(it))); } } else { // first find the largest range - const auto lower_bound_first = std::lower_bound(mData.begin(), mData.end(), KeyOf(**(first.base())), CompareKey()); - const auto upper_bound_last = std::upper_bound(lower_bound_first, mData.end(), KeyOf(**((last-1).base())), CompareKey()); + const auto lower_bound_first = std::lower_bound(mData.begin(), mData.end(), KeyOf(GetReference(first)), CompareKey()); + const auto upper_bound_last = std::upper_bound(lower_bound_first, mData.end(), KeyOf(GetReference(last-1)), CompareKey()); // then find the compact sub range - const auto upper_bound_first = std::upper_bound(lower_bound_first, upper_bound_last, KeyOf(**(first.base())), CompareKey()); - const auto lower_bound_last = std::lower_bound(lower_bound_first, upper_bound_last, KeyOf(**((last-1).base())), CompareKey()); + const auto upper_bound_first = std::upper_bound(lower_bound_first, upper_bound_last, KeyOf(GetReference(first)), CompareKey()); + const auto lower_bound_last = std::lower_bound(lower_bound_first, upper_bound_last, KeyOf(GetReference(last-1)), CompareKey()); if (lower_bound_first == lower_bound_last && lower_bound_first == upper_bound_first && @@ -1087,12 +1087,12 @@ class PointerVectorSet final // all 4 bounds are equal, hence this can be inserted without checking further if (lower_bound_first == mData.end()) { for (auto it = first; it != last; ++it) { - mData.push_back(TPointerType(*(it.base()))); + mData.push_back(TPointerType(&GetReference(it))); } } else { auto current_pos = lower_bound_first - 1; for (auto it = first; it != last; ++it) { - current_pos = mData.insert(current_pos + 1, TPointerType(*(it.base()))); + current_pos = mData.insert(current_pos + 1, TPointerType(&GetReference(it))); } } } else { @@ -1100,9 +1100,9 @@ class PointerVectorSet final // now add the new elements for (auto it = first; it != last; ++it) { // find the lower bound element. - p_current_itr = std::lower_bound(p_current_itr, mData.end(), KeyOf(**(it.base())), CompareKey()); - if (p_current_itr == mData.end() || !EqualKeyTo(KeyOf(**(it.base())))(*p_current_itr)) { - p_current_itr = mData.insert(p_current_itr, TPointerType(*(it.base()))); + p_current_itr = std::lower_bound(p_current_itr, mData.end(), KeyOf(GetReference(it)), CompareKey()); + if (p_current_itr == mData.end() || !EqualKeyTo(KeyOf(GetReference(it)))(*p_current_itr)) { + p_current_itr = mData.insert(p_current_itr, TPointerType(&GetReference(it))); } } } @@ -1147,6 +1147,37 @@ class PointerVectorSet final return TGetKeyType()(i); } + /** + * @brief Get the reference from an iterator. + * + * This method is used to get reference from an iterator. This is required to support + * both PointerVectorSet::iterator and std::vector::iterators because, their + * "*" operators returns different types of objects. + * + */ + template + inline auto& GetReference(TIteratorType Iterator) const + { + // It is difficult to use std::iterator_traits to get the value + // type of the iterator because, boost::indirect has a value type + // which is harder to guess, and cryptic. Hence, using the decltype. + using iterator_value_type = std::decay_t; + + if constexpr(std::is_same_v>) { + // in here, std::remove_cv is only used for the value_type because, + // the PointerVectorSet can be with TDataType which is const, but the passed pointers + // must be always TDataType::Pointer which is defined for non cost TDataType. This is + // a valid use case. Other way is not possible, hence std::remove_cv is not used on + // iterator_value_type. + return *Iterator; + } else if constexpr(std::is_same_v) { + return **Iterator; + } else { + static_assert(!std::is_same_v, "Unsupported iterator type."); + return 0; + } + } + ///@} ///@name Serialization ///@{ From f84b13566680d3bd1536ae73cff783ac86118da5 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Wed, 29 May 2024 07:45:42 +0200 Subject: [PATCH 21/26] add reserve --- kratos/containers/pointer_vector_set.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index dfc899966c56..107a470d867c 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -1085,6 +1085,7 @@ class PointerVectorSet final lower_bound_first == upper_bound_last) { // all 4 bounds are equal, hence this can be inserted without checking further + mData.reserve(mData.size() + std::distance(first, last)); if (lower_bound_first == mData.end()) { for (auto it = first; it != last; ++it) { mData.push_back(TPointerType(&GetReference(it))); From b82885c9a18f614d4c4435a60e093ec40dc521b2 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Wed, 29 May 2024 07:52:28 +0200 Subject: [PATCH 22/26] avoid calling insert --- kratos/containers/pointer_vector_set.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index 107a470d867c..535c58701483 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -611,7 +611,9 @@ class PointerVectorSet final return iterator(mData.end() - 1); } else { // given position is invalid. Hence, discarding the hint. - return insert(value); + auto itr_pos = std::lower_bound(mData.begin(), mData.end(), KeyOf(*value), CompareKey()); + mSortedPartSize = mData.size() + 1; + return mData.insert(itr_pos, value); } } else if (position_hint == cbegin()) { // trying to insert at the front. @@ -622,7 +624,9 @@ class PointerVectorSet final return mData.insert(mData.begin(), value); } else { // given position is invalid. Hence, discarding the hint. - return insert(value); + auto itr_pos = std::lower_bound(mData.begin(), mData.end(), KeyOf(*value), CompareKey()); + mSortedPartSize = mData.size() + 1; + return mData.insert(itr_pos, value); } } else { // trying to insert at an arbitrary position. @@ -631,7 +635,9 @@ class PointerVectorSet final return mData.insert(mData.begin() + (position_hint - cbegin()), value); } else { // given position is invalid. Hence, discarding the hint. - return insert(value); + auto itr_pos = std::lower_bound(mData.begin(), mData.end(), KeyOf(*value), CompareKey()); + mSortedPartSize = mData.size() + 1; + return mData.insert(itr_pos, value); } } } From 0555c333bfc31639441f69989ece81c2376e8375 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Wed, 5 Jun 2024 12:05:17 +0200 Subject: [PATCH 23/26] change name --- .../{set_function.h => key_generator.h} | 16 +++---- kratos/containers/pointer_vector_set.h | 42 +++++++++++-------- 2 files changed, 32 insertions(+), 26 deletions(-) rename kratos/containers/{set_function.h => key_generator.h} (83%) diff --git a/kratos/containers/set_function.h b/kratos/containers/key_generator.h similarity index 83% rename from kratos/containers/set_function.h rename to kratos/containers/key_generator.h index ae1c9b58a17f..2297d2792680 100644 --- a/kratos/containers/set_function.h +++ b/kratos/containers/key_generator.h @@ -44,7 +44,7 @@ struct TestOperators }; /** - * @class SetFunction + * @class KeyGenerator * @brief A functor that serves as the identity function if "<" and "==" operators are defined, otherwise, returns memory location. * @details This class provides two overloaded operator() functions, one for non-const objects * and another for const objects. The operator() returns the input objects memory location as it is, @@ -59,7 +59,7 @@ struct TestOperators * @author Suneth Warnakulasuriya */ template -class SetFunction +class KeyGenerator { private: ///@name Private static variables @@ -78,10 +78,10 @@ class SetFunction ///@{ /** - * @brief Operator that returns a non-const reference pointer to the input object if "<" and "==" operators are defined. - * Otherwise this returns a reference to the input object. + * @brief Operator that returns a non-const reference to the input object if "<" and "==" operators are defined. + * Otherwise this returns a pointer to the input object. * @param data The input object of type TDataType. - * @return A non-const reference pointer or reference to the same object as provided in the parameter. + * @return A non-const reference or pointer to the same object as provided in the parameter. */ std::conditional_t operator()(TDataType& rData) { @@ -93,10 +93,10 @@ class SetFunction } /** - * @brief Operator that returns a const reference pointer to the input object if "<" and "==" operators are defined. - * Otherwise this returns the const reference to the input object. + * @brief Operator that returns a const reference to the input object if "<" and "==" operators are defined. + * Otherwise this returns a pointer to the const input object. * @param data The input object of type TDataType. - * @return A const reference pointer or reference to the same object as provided in the parameter. + * @return A const reference or pointer to the same object as provided in the parameter. */ std::conditional_t operator()(const TDataType& rData) const { diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index 535c58701483..194a1fc6991a 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -27,7 +27,7 @@ // Project includes #include "includes/define.h" #include "includes/serializer.h" -#include "containers/set_function.h" +#include "containers/key_generator.h" namespace Kratos { @@ -63,7 +63,7 @@ namespace Kratos * @author Pooyan Dadvand */ template, + class TGetKeyType = KeyGenerator, class TCompareType = std::less()(std::declval()))>, class TEqualType = std::equal_to()(std::declval()))>, class TPointerType = typename TDataType::Pointer, @@ -574,13 +574,8 @@ class PointerVectorSet final mData.push_back(value); mSortedPartSize = mData.size(); return iterator(mData.end() - 1); - } else if (EqualKeyTo(KeyOf(*value))(*itr_pos)) { - // already found existing element with the same key, hence returning the existing element. - return iterator(itr_pos); } else { - // insert the new value before the itr_pos. - mSortedPartSize = mData.size() + 1; - return mData.insert(itr_pos, value); + return UniqueInsert(value); } } @@ -611,9 +606,7 @@ class PointerVectorSet final return iterator(mData.end() - 1); } else { // given position is invalid. Hence, discarding the hint. - auto itr_pos = std::lower_bound(mData.begin(), mData.end(), KeyOf(*value), CompareKey()); - mSortedPartSize = mData.size() + 1; - return mData.insert(itr_pos, value); + return UniqueInsert(value); } } else if (position_hint == cbegin()) { // trying to insert at the front. @@ -624,9 +617,7 @@ class PointerVectorSet final return mData.insert(mData.begin(), value); } else { // given position is invalid. Hence, discarding the hint. - auto itr_pos = std::lower_bound(mData.begin(), mData.end(), KeyOf(*value), CompareKey()); - mSortedPartSize = mData.size() + 1; - return mData.insert(itr_pos, value); + return UniqueInsert(value); } } else { // trying to insert at an arbitrary position. @@ -635,9 +626,7 @@ class PointerVectorSet final return mData.insert(mData.begin() + (position_hint - cbegin()), value); } else { // given position is invalid. Hence, discarding the hint. - auto itr_pos = std::lower_bound(mData.begin(), mData.end(), KeyOf(*value), CompareKey()); - mSortedPartSize = mData.size() + 1; - return mData.insert(itr_pos, value); + return UniqueInsert(value); } } } @@ -1097,7 +1086,11 @@ class PointerVectorSet final mData.push_back(TPointerType(&GetReference(it))); } } else { - auto current_pos = lower_bound_first - 1; + // now if the capacity of the new mData is larger than the existing + // capacity, then the current lower_bound_first is invalidated. + // hence needs to find it again. + const auto new_lower_bound = std::lower_bound(mData.begin(), mData.end(), KeyOf(GetReference(first)), CompareKey()); + auto current_pos = new_lower_bound - 1; for (auto it = first; it != last; ++it) { current_pos = mData.insert(current_pos + 1, TPointerType(&GetReference(it))); } @@ -1185,6 +1178,19 @@ class PointerVectorSet final } } + iterator UniqueInsert(const TPointerType& value) + { + auto itr_pos = std::lower_bound(mData.begin(), mData.end(), KeyOf(*value), CompareKey()); + if (EqualKeyTo(KeyOf(*value))(*itr_pos)) { + // already found existing element with the same key, hence returning the existing element. + return iterator(itr_pos); + } else { + // insert the new value before the itr_pos. + mSortedPartSize = mData.size() + 1; + return mData.insert(itr_pos, value); + } + } + ///@} ///@name Serialization ///@{ From 4e5f7411fa68060e6fe4fdab0f610a181c4b2f7c Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Wed, 5 Jun 2024 12:05:26 +0200 Subject: [PATCH 24/26] add additional iterator tests --- .../containers/test_pointer_vector_set.cpp | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp b/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp index c71b995b16d2..39729ee27777 100644 --- a/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp +++ b/kratos/tests/cpp_tests/containers/test_pointer_vector_set.cpp @@ -52,13 +52,13 @@ KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert1, KratosCoreFastSuite) auto p_element_5 = Kratos::make_intrusive(5); auto p_element_6 = Kratos::make_intrusive(6); auto p_element_3_ptr_copy = Kratos::intrusive_ptr(p_element_3); - test_container.insert(p_element_3); - test_container.insert(p_element_2); - test_container.insert(p_element_1); - test_container.insert(p_element_5); - test_container.insert(p_element_6); - test_container.insert(p_element_4); - test_container.insert(p_element_3_ptr_copy); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_3), &*p_element_3); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_2), &*p_element_2); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_1), &*p_element_1); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_5), &*p_element_5); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_6), &*p_element_6); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_4), &*p_element_4); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_3_ptr_copy), &*p_element_3); KRATOS_EXPECT_EQ(test_container.size(), 6); @@ -78,13 +78,13 @@ KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert2, KratosCoreFastSuite) auto p_element_5 = Kratos::make_intrusive(5); auto p_element_6 = Kratos::make_intrusive(6); auto p_element_3_copy = Kratos::make_intrusive(3); - test_container.insert(p_element_3); - test_container.insert(p_element_2); - test_container.insert(p_element_1); - test_container.insert(p_element_5); - test_container.insert(p_element_6); - test_container.insert(p_element_4); - test_container.insert(p_element_3_copy); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_3), &*p_element_3); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_2), &*p_element_2); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_1), &*p_element_1); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_5), &*p_element_5); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_6), &*p_element_6); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_4), &*p_element_4); + KRATOS_EXPECT_EQ(&*test_container.insert(p_element_3_copy), &*p_element_3); KRATOS_EXPECT_EQ(test_container.size(), 6); @@ -107,13 +107,14 @@ KRATOS_TEST_CASE_IN_SUITE(PointerVectorSetInsert3, KratosCoreFastSuite) auto p_element_5 = Kratos::make_intrusive(5); auto p_element_6 = Kratos::make_intrusive(6); auto p_element_3_ptr_copy = Kratos::intrusive_ptr(p_element_3); - test_container.insert(test_container.end(), p_element_3); - test_container.insert(test_container.end(), p_element_6); - test_container.insert(test_container.end(), p_element_2); - test_container.insert(test_container.begin(), p_element_1); - test_container.insert(test_container.begin(), p_element_5); - test_container.insert(test_container.begin() + 3, p_element_4); - test_container.insert(test_container.begin() + 3, p_element_1); + KRATOS_EXPECT_EQ(&*test_container.insert(test_container.end(), p_element_3), &*p_element_3); + KRATOS_EXPECT_EQ(&*test_container.insert(test_container.end(), p_element_6), &*p_element_6); + KRATOS_EXPECT_EQ(&*test_container.insert(test_container.end(), p_element_2), &*p_element_2); + KRATOS_EXPECT_EQ(&*test_container.insert(test_container.begin(), p_element_1), &*p_element_1); + KRATOS_EXPECT_EQ(&*test_container.insert(test_container.begin(), p_element_5), &*p_element_5); + KRATOS_EXPECT_EQ(&*test_container.insert(test_container.begin() + 3, p_element_4), &*p_element_4); + KRATOS_EXPECT_EQ(&*test_container.insert(test_container.begin() + 3, p_element_1), &*p_element_1); + KRATOS_EXPECT_EQ(&*test_container.insert(test_container.begin() + 3, p_element_3_ptr_copy), &*p_element_3); KRATOS_EXPECT_EQ(test_container.size(), 6); From 2cfaa7b0d3cae616d4e6e55e07609bad07103968 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Wed, 5 Jun 2024 12:38:40 +0200 Subject: [PATCH 25/26] remove operator def --- .../MappingApplication/custom_utilities/closest_points.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/applications/MappingApplication/custom_utilities/closest_points.cpp b/applications/MappingApplication/custom_utilities/closest_points.cpp index cef96b935d52..1a9ab670743b 100644 --- a/applications/MappingApplication/custom_utilities/closest_points.cpp +++ b/applications/MappingApplication/custom_utilities/closest_points.cpp @@ -45,11 +45,6 @@ bool PointWithId::operator!=(const PointWithId& rOther) const return (!Point::operator==(rOther)); } -bool PointWithId::operator==(const PointWithId& rOther) const -{ - return Point::operator==(rOther); -} - void PointWithId::save(Serializer &rSerializer) const { KRATOS_SERIALIZE_SAVE_BASE_CLASS(rSerializer, IndexedObject); From 359f87e7737a161cf9c5962cb47313b71d0a22d3 Mon Sep 17 00:00:00 2001 From: sunethwarna Date: Wed, 5 Jun 2024 13:22:18 +0200 Subject: [PATCH 26/26] revert --- kratos/containers/pointer_vector_set.h | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/kratos/containers/pointer_vector_set.h b/kratos/containers/pointer_vector_set.h index 194a1fc6991a..f64b7068c538 100644 --- a/kratos/containers/pointer_vector_set.h +++ b/kratos/containers/pointer_vector_set.h @@ -574,8 +574,13 @@ class PointerVectorSet final mData.push_back(value); mSortedPartSize = mData.size(); return iterator(mData.end() - 1); + } else if (EqualKeyTo(KeyOf(*value))(*itr_pos)) { + // already found existing element with the same key, hence returning the existing element. + return iterator(itr_pos); } else { - return UniqueInsert(value); + // insert the new value before the itr_pos. + mSortedPartSize = mData.size() + 1; + return mData.insert(itr_pos, value); } } @@ -606,7 +611,7 @@ class PointerVectorSet final return iterator(mData.end() - 1); } else { // given position is invalid. Hence, discarding the hint. - return UniqueInsert(value); + return insert(value); } } else if (position_hint == cbegin()) { // trying to insert at the front. @@ -617,7 +622,7 @@ class PointerVectorSet final return mData.insert(mData.begin(), value); } else { // given position is invalid. Hence, discarding the hint. - return UniqueInsert(value); + return insert(value); } } else { // trying to insert at an arbitrary position. @@ -626,7 +631,7 @@ class PointerVectorSet final return mData.insert(mData.begin() + (position_hint - cbegin()), value); } else { // given position is invalid. Hence, discarding the hint. - return UniqueInsert(value); + return insert(value); } } } @@ -1178,19 +1183,6 @@ class PointerVectorSet final } } - iterator UniqueInsert(const TPointerType& value) - { - auto itr_pos = std::lower_bound(mData.begin(), mData.end(), KeyOf(*value), CompareKey()); - if (EqualKeyTo(KeyOf(*value))(*itr_pos)) { - // already found existing element with the same key, hence returning the existing element. - return iterator(itr_pos); - } else { - // insert the new value before the itr_pos. - mSortedPartSize = mData.size() + 1; - return mData.insert(itr_pos, value); - } - } - ///@} ///@name Serialization ///@{