{"action":"created","comment":{"url":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/comments/231025982","pull_request_review_id":171896114,"id":231025982,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzMTAyNTk4Mg==","diff_hunk":"@@ -0,0 +1,1288 @@\n+//    |  /           |\n+//    ' /   __| _` | __|  _ \\   __|\n+//    . \\  |   (   | |   (   |\\__ `\n+//   _|\\_\\_|  \\__,_|\\__|\\___/ ____/\n+//                   Multi-Physics\n+//\n+//  License:         BSD License\n+//                     Kratos default license: kratos/license.txt\n+//\n+//  Main authors:    Vicente Mataix Ferrandiz\n+//\n+//\n+#if !defined(KRATOS_RESIDUAL_BASED_ELIMINATION_BUILDER_AND_SOLVER_WITH_CONSTRAINTS)\n+#define KRATOS_RESIDUAL_BASED_ELIMINATION_BUILDER_AND_SOLVER_WITH_CONSTRAINTS\n+\n+/* System includes */\n+#include <unordered_set>\n+#include <map>\n+#include <unordered_map>\n+\n+/* External includes */\n+\n+/* Project includes */\n+#include \"solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver.h\"\n+#include \"includes/master_slave_constraint.h\"\n+#include \"utilities/sparse_matrix_multiplication_utility.h\"\n+#include \"utilities/helper_classes_for_constraint_builder.h\"\n+\n+#include \"containers/pointer_vector_map.h\"\n+#include \"containers/pointer_hash_map_set.h\"\n+#include \"containers/data_value_container.h\"\n+#include \"input_output/logger.h\"\n+\n+namespace Kratos\n+{\n+\n+///@name Kratos Globals\n+///@{\n+\n+///@}\n+///@name Type Definitions\n+///@{\n+\n+///@}\n+///@name  Enum's\n+///@{\n+\n+///@}\n+///@name  Functions\n+///@{\n+\n+///@}\n+///@name Kratos Classes\n+///@{\n+\n+/**\n+ * @class ResidualBasedEliminationBuilderAndSolverWithConstraints\n+ * @ingroup KratosCore\n+ * @brief Current class provides an implementation for standard builder and solving operations.\n+ * @details The RHS is constituted by the unbalanced loads (residual)\n+ * Degrees of freedom are reordered putting the restrained degrees of freedom at\n+ * the end of the system ordered in reverse order with respect to the DofSet.\n+ * Imposition of the dirichlet conditions is naturally dealt with as the residual already contains\n+ * this information.\n+ * Calculation of the reactions involves a cost very similiar to the calculation of the total residual\n+ * @author Vicente Mataix Ferrandiz\n+ */\n+template <class TSparseSpace,\n+          class TDenseSpace,\n+          class TLinearSolver\n+          >\n+class ResidualBasedEliminationBuilderAndSolverWithConstraints\n+    : public ResidualBasedEliminationBuilderAndSolver<TSparseSpace, TDenseSpace, TLinearSolver>\n+{\n+  public:\n+    ///@name Type Definitions\n+    ///@{\n+\n+    /// Pointer definition of ResidualBasedEliminationBuilderAndSolverWithConstraints\n+    KRATOS_CLASS_POINTER_DEFINITION(ResidualBasedEliminationBuilderAndSolverWithConstraints);\n+\n+    /// Definition of the base class\n+    typedef ResidualBasedEliminationBuilderAndSolver<TSparseSpace, TDenseSpace, TLinearSolver> BaseType;\n+\n+    // The size_t types\n+    typedef std::size_t SizeType;\n+    typedef std::size_t IndexType;\n+\n+    /// Definition of the classes from the base class\n+    typedef typename BaseType::TSchemeType TSchemeType;\n+    typedef typename BaseType::TDataType TDataType;\n+    typedef typename BaseType::DofsArrayType DofsArrayType;\n+    typedef typename BaseType::TSystemMatrixType TSystemMatrixType;\n+    typedef typename BaseType::TSystemVectorType TSystemVectorType;\n+    typedef typename BaseType::LocalSystemVectorType LocalSystemVectorType;\n+    typedef typename BaseType::LocalSystemMatrixType LocalSystemMatrixType;\n+    typedef typename BaseType::TSystemMatrixPointerType TSystemMatrixPointerType;\n+    typedef typename BaseType::TSystemVectorPointerType TSystemVectorPointerType;\n+    typedef typename BaseType::NodeType NodeType;\n+    typedef typename BaseType::NodesArrayType NodesArrayType;\n+    typedef typename BaseType::ElementsArrayType ElementsArrayType;\n+    typedef typename BaseType::ConditionsArrayType ConditionsArrayType;\n+\n+    /// Additional definitions\n+    typedef PointerVectorSet<Element, IndexedObject> ElementsContainerType;\n+    typedef Element::EquationIdVectorType EquationIdVectorType;\n+    typedef Element::DofsVectorType DofsVectorType;\n+    typedef boost::numeric::ublas::compressed_matrix<double> CompressedMatrixType;\n+\n+    /// DoF types definition\n+    typedef typename NodeType::DofType DofType;\n+    typedef typename DofType::Pointer DofPointerType;\n+\n+    /// Set definition\n+    typedef std::unordered_set<IndexType> IndexSetType;\n+\n+    /// MPC definitions\n+    typedef MasterSlaveConstraint MasterSlaveConstraintType;\n+    typedef typename MasterSlaveConstraint::Pointer MasterSlaveConstraintPointerType;\n+    typedef Internals::AuxiliaryGlobalMasterSlaveConstraint AuxiliaryGlobalMasterSlaveConstraintType;\n+    typedef Internals::GlobalMasterSlaveRelationContainerType GlobalMasterSlaveRelationContainerType;\n+    typedef std::vector<IndexType> VectorIndexType;\n+    typedef Vector VectorType;\n+    typedef Internals::ConstraintImposer<TSparseSpace, TDenseSpace, TLinearSolver> ConstraintImposerType;\n+\n+    ///@}\n+    ///@name  Enum's\n+    ///@{\n+\n+    ///@}\n+    ///@name Life Cycle\n+    ///@{\n+\n+    /**\n+     * @brief Default constructor. (with parameters)\n+     */\n+    explicit ResidualBasedEliminationBuilderAndSolverWithConstraints(\n+        typename TLinearSolver::Pointer pNewLinearSystemSolver,\n+        Parameters ThisParameters\n+        ) : BaseType(pNewLinearSystemSolver)\n+//         ) : BaseType(pNewLinearSystemSolver, ThisParameters)\n+    {\n+    }\n+\n+    /**\n+     * @brief Default constructor\n+     */\n+    explicit ResidualBasedEliminationBuilderAndSolverWithConstraints(\n+        typename TLinearSolver::Pointer pNewLinearSystemSolver)\n+        : BaseType(pNewLinearSystemSolver)\n+    {\n+    }\n+\n+    /** Destructor.\n+     */\n+    ~ResidualBasedEliminationBuilderAndSolverWithConstraints() override\n+    {\n+    }\n+\n+    ///@}\n+    ///@name Operators\n+    ///@{\n+\n+    ///@}\n+    ///@name Operations\n+    ///@{\n+\n+    void SetUpSystem(ModelPart& rModelPart) override\n+    {\n+        if(rModelPart.MasterSlaveConstraints().size() > 0)\n+            SetUpSystemWithConstraints(rModelPart);\n+        else\n+            BaseType::SetUpSystem(rModelPart);\n+    }\n+\n+    /**\n+     * @brief Function to perform the build of the RHS. The vector could be sized as the total number\n+     * of dofs or as the number of unrestrained ones\n+     * @param pScheme The integration scheme considered\n+     * @param rModelPart The model part of the problem to solve\n+     * @param rA The LHS matrix\n+     * @param rb The RHS vector\n+     */\n+    void Build(\n+        typename TSchemeType::Pointer pScheme,\n+        ModelPart& rModelPart,\n+        TSystemMatrixType& rA,\n+        TSystemVectorType& rb\n+        ) override\n+    {\n+        if(rModelPart.MasterSlaveConstraints().size() > 0)\n+            BuildWithConstraints(pScheme, rModelPart, rA, rb);\n+        else\n+            BaseType::Build(pScheme, rModelPart, rA, rb);\n+    }\n+\n+    /**\n+     * @brief Function to perform the building and solving phase at the same time.\n+     * @details It is ideally the fastest and safer function to use when it is possible to solve\n+     * just after building\n+     * @param pScheme The integration scheme considered\n+     * @param rModelPart The model part of the problem to solve\n+     * @param A The LHS matrix\n+     * @param Dx The Unknowns vector\n+     * @param b The RHS vector\n+     */\n+    void BuildAndSolve(\n+        typename TSchemeType::Pointer pScheme,\n+        ModelPart& rModelPart,\n+        TSystemMatrixType& A,\n+        TSystemVectorType& Dx,\n+        TSystemVectorType& b) override\n+    {\n+        if(rModelPart.MasterSlaveConstraints().size() > 0)\n+            BuildAndSolveWithConstraints(pScheme, rModelPart, A, Dx, b);\n+        else\n+            BaseType::BuildAndSolve(pScheme, rModelPart, A, Dx, b);\n+    }\n+\n+    /**\n+     * @brief Builds the list of the DofSets involved in the problem by \"asking\" to each element\n+     * and condition its Dofs.\n+     * @details The list of dofs is stores insde the BuilderAndSolver as it is closely connected to the\n+     * way the matrix and RHS are built\n+     * @param pScheme The integration scheme considered\n+     * @param rModelPart The model part of the problem to solve\n+     */\n+    void SetUpDofSet(\n+        typename TSchemeType::Pointer pScheme,\n+        ModelPart& rModelPart\n+        ) override\n+    {\n+        KRATOS_TRY;\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", ( this->GetEchoLevel() > 1 && rModelPart.GetCommunicator().MyPID() == 0)) << \"Setting up the dofs\" << std::endl;\n+\n+        DofsVectorType dof_list, auxiliar_dof_list;\n+\n+        ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo();\n+\n+        typedef std::unordered_set < DofPointerType, DofPointerHasher> set_type;\n+\n+        // Declaring temporal variables\n+        DofsArrayType dof_temp_all, dof_temp_solvable;\n+        BaseType::mDofSet = DofsArrayType();\n+        mDoFToSolveSet = DofsArrayType();\n+\n+        set_type dof_global_set;\n+\n+        #pragma omp parallel firstprivate(dof_list)\n+        {\n+            set_type dofs_tmp_set;\n+            dofs_tmp_set.reserve(20000);\n+\n+            // Gets the array of elements from the modeler\n+            ElementsArrayType& r_elements_array = rModelPart.Elements();\n+            const int number_of_elements = static_cast<int>(r_elements_array.size());\n+            #pragma omp for schedule(guided, 512) nowait\n+            for (int i = 0; i < number_of_elements; ++i) {\n+                auto it_elem = r_elements_array.begin() + i;\n+\n+                // Gets list of Dof involved on every element\n+                pScheme->GetElementalDofList(*(it_elem.base()), dof_list, r_current_process_info);\n+                dofs_tmp_set.insert(dof_list.begin(), dof_list.end());\n+            }\n+\n+            // Gets the array of conditions from the modeler\n+            ConditionsArrayType& r_conditions_array = rModelPart.Conditions();\n+            const int number_of_conditions = static_cast<int>(r_conditions_array.size());\n+            #pragma omp for  schedule(guided, 512)\n+            for (int i = 0; i < number_of_conditions; ++i) {\n+                auto it_cond = r_conditions_array.begin() + i;\n+\n+                // Gets list of Dof involved on every element\n+                pScheme->GetConditionDofList(*(it_cond.base()), dof_list, r_current_process_info);\n+                dofs_tmp_set.insert(dof_list.begin(), dof_list.end());\n+            }\n+\n+            auto& r_constraints_array = rModelPart.MasterSlaveConstraints();\n+            const int number_of_constraints = static_cast<int>(r_constraints_array.size());\n+            #pragma omp for  schedule(guided, 512)\n+            for (int i = 0; i < number_of_constraints; ++i) {\n+                auto it_const = r_constraints_array.begin() + i;\n+\n+                // Gets list of Dof involved on every element\n+                it_const->GetDofList(dof_list, auxiliar_dof_list, r_current_process_info);\n+                dofs_tmp_set.insert(dof_list.begin(), dof_list.end());\n+                dofs_tmp_set.insert(auxiliar_dof_list.begin(), auxiliar_dof_list.end());\n+            }\n+\n+            #pragma omp critical\n+            {\n+                dof_global_set.insert(dofs_tmp_set.begin(), dofs_tmp_set.end());\n+            }\n+        }\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", ( this->GetEchoLevel() > 2)) << \"Initializing ordered array filling\\n\" << std::endl;\n+\n+        dof_temp_all.reserve(dof_global_set.size());\n+        for (auto& dof : dof_global_set) {\n+            dof_temp_all.push_back( dof.get() );\n+        }\n+        dof_temp_all.Sort();\n+        BaseType::mDofSet = dof_temp_all;\n+\n+        // Repeating the loop for solvable DoF (in serial)\n+        set_type dofs_aux_list_solvable;\n+        // Gets the array of elements from the modeler\n+        ElementsArrayType& r_elements_array = rModelPart.Elements();\n+        const int number_of_elements = static_cast<int>(r_elements_array.size());\n+        #pragma omp for schedule(guided, 512) nowait\n+        for (int i = 0; i < number_of_elements; ++i) {\n+            auto it_elem = r_elements_array.begin() + i;\n+\n+            // Gets list of Dof involved on every element\n+            pScheme->GetElementalDofList(*(it_elem.base()), dof_list, r_current_process_info);\n+            dofs_aux_list_solvable.insert(dof_list.begin(), dof_list.end());\n+        }\n+\n+        // Gets the array of conditions from the modeler\n+        ConditionsArrayType& r_conditions_array = rModelPart.Conditions();\n+        const int number_of_conditions = static_cast<int>(r_conditions_array.size());\n+        #pragma omp for  schedule(guided, 512)\n+        for (int i = 0; i < number_of_conditions; ++i) {\n+            auto it_cond = r_conditions_array.begin() + i;\n+\n+            // Gets list of Dof involved on every element\n+            pScheme->GetConditionDofList(*(it_cond.base()), dof_list, r_current_process_info);\n+            dofs_aux_list_solvable.insert(dof_list.begin(), dof_list.end());\n+        }\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", ( this->GetEchoLevel() > 2)) << \"Initializing constraints loop\" << std::endl;\n+\n+        // We don't do a loop in OMP because erase is not a parallel threadsafe operation\n+        auto& r_constraints_array = rModelPart.MasterSlaveConstraints();\n+        const int number_of_constraints = static_cast<int>(r_constraints_array.size());\n+\n+        for (int i = 0; i < number_of_constraints; ++i) {\n+            auto it_const = r_constraints_array.begin() + i;\n+\n+            // Gets list of Dof involved on every element\n+            it_const->GetDofList(dof_list, auxiliar_dof_list, r_current_process_info);\n+            // We remove the slave dofs\n+            for (auto& dof : dof_list) {\n+                auto it = dofs_aux_list_solvable.find(dof);\n+                // Check if Iterator is valid\n+                if(it != dofs_aux_list_solvable.end())\n+                    dofs_aux_list_solvable.erase(it);\n+            }\n+            dofs_aux_list_solvable.insert(auxiliar_dof_list.begin(), auxiliar_dof_list.end()); // We add the master dofs\n+        }\n+\n+        dof_temp_solvable.reserve(dofs_aux_list_solvable.size());\n+        for (auto& dof : dofs_aux_list_solvable) {\n+            dof_temp_solvable.push_back( dof.get() );\n+        }\n+        dof_temp_solvable.Sort();\n+        mDoFToSolveSet = dof_temp_solvable;\n+\n+        // Throws an exception if there are no Degrees Of Freedom involved in the analysis\n+        KRATOS_ERROR_IF(BaseType::mDofSet.size() == 0) << \"No degrees of freedom!\" << std::endl;\n+        KRATOS_ERROR_IF( mDoFToSolveSet.size() == 0) << \"No degrees of freedom to solve!\" << std::endl;\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", ( this->GetEchoLevel() > 2)) << \"Number of degrees of freedom:\" << BaseType::mDofSet.size() << std::endl;\n+\n+        BaseType::mDofSetIsInitialized = true;\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", ( this->GetEchoLevel() > 2 && rModelPart.GetCommunicator().MyPID() == 0)) << \"Finished setting up the dofs\" << std::endl;\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", ( this->GetEchoLevel() > 2)) << \"Initializing lock array\" << std::endl;\n+\n+#ifdef _OPENMP\n+        if (BaseType::mlock_array.size() != 0) {\n+            for (int i = 0; i < static_cast<int>(BaseType::mlock_array.size()); ++i) {\n+                omp_destroy_lock(&BaseType::mlock_array[i]);\n+            }\n+        }\n+        BaseType::mlock_array.resize(BaseType::mDofSet.size());\n+\n+        for (int i = 0; i < static_cast<int>(BaseType::mlock_array.size()); ++i) {\n+            omp_init_lock(&BaseType::mlock_array[i]);\n+        }\n+#endif\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", ( this->GetEchoLevel() > 2)) << \"End of setup dof set\\n\" << std::endl;\n+\n+    // If reactions are to be calculated, we check if all the dofs have reactions defined\n+    // This is tobe done only in debug mode\n+    #ifdef KRATOS_DEBUG\n+        if(BaseType::GetCalculateReactionsFlag()) {\n+            for(auto dof_iterator = BaseType::mDofSet.begin(); dof_iterator != BaseType::mDofSet.end(); ++dof_iterator) {\n+                KRATOS_ERROR_IF_NOT(dof_iterator->HasReaction()) << \"Reaction variable not set for the following : \" << std::endl\n+                    << \"Node : \" << dof_iterator->Id()<< std::endl\n+                    << \"Dof : \" << (*dof_iterator) << std::endl << \"Not possible to calculate reactions.\" << std::endl;\n+            }\n+        }\n+    #endif\n+\n+        KRATOS_CATCH(\"\");\n+    }\n+\n+    /**\n+     * @brief It applies certain operations at the system of equations at the begining of the solution step\n+     * @param rModelPart The model part to compute\n+     * @param rA The LHS matrix of the system of equations\n+     * @param rDx The vector of unkowns\n+     * @param rb The RHS vector of the system of equations\n+     */\n+    void InitializeSolutionStep(\n+        ModelPart& rModelPart,\n+        TSystemMatrixType& rA,\n+        TSystemVectorType& rDx,\n+        TSystemVectorType& rb\n+        ) override\n+    {\n+        KRATOS_TRY\n+\n+        BaseType::InitializeSolutionStep(rModelPart, rA, rDx, rb);\n+\n+        // Getting process info\n+        const ProcessInfo& r_process_info = rModelPart.GetProcessInfo();\n+\n+        // Computing constraints\n+        const int n_constraints = static_cast<int>(rModelPart.MasterSlaveConstraints().size());\n+        auto constraints_begin = rModelPart.MasterSlaveConstraintsBegin();\n+        #pragma omp parallel for schedule(guided, 512) firstprivate(n_constraints, constraints_begin)\n+        for (int k = 0; k < n_constraints; ++k) {\n+            auto it = constraints_begin + k;\n+            it->InitializeSolutionStep(r_process_info); // Here each constraint constructs and stores its T and C matrices. Also its equation slave_ids.\n+        }\n+\n+        KRATOS_CATCH(\"ResidualBasedEliminationBuilderAndSolverWithConstraints failed to initialize solution step.\")\n+    }\n+\n+    /**\n+     * @brief It applies certain operations at the system of equations at the end of the solution step\n+     * @param rModelPart The model part to compute\n+     * @param rA The LHS matrix of the system of equations\n+     * @param rDx The vector of unkowns\n+     * @param rb The RHS vector of the system of equations\n+     */\n+    void FinalizeSolutionStep(\n+        ModelPart& rModelPart,\n+        TSystemMatrixType& rA,\n+        TSystemVectorType& rDx,\n+        TSystemVectorType& rb\n+        ) override\n+    {\n+        KRATOS_TRY\n+        BaseType::FinalizeSolutionStep(rModelPart, rA, rDx, rb);\n+\n+        // Getting process info\n+        const ProcessInfo& r_process_info = rModelPart.GetProcessInfo();\n+\n+        // Computing constraints\n+        const int n_constraints = static_cast<int>(rModelPart.MasterSlaveConstraints().size());\n+        const auto constraints_begin = rModelPart.MasterSlaveConstraintsBegin();\n+        #pragma omp parallel for schedule(guided, 512) firstprivate(n_constraints, constraints_begin)\n+        for (int k = 0; k < n_constraints; ++k) {\n+            auto it = constraints_begin + k;\n+            it->FinalizeSolutionStep(r_process_info);\n+        }\n+        KRATOS_CATCH(\"ResidualBasedEliminationBuilderAndSolverWithConstraints failed to finalize solution step.\")\n+    }\n+\n+    ///@}\n+    ///@name Access\n+    ///@{\n+\n+    ///@}\n+    ///@name Inquiry\n+    ///@{\n+\n+    ///@}\n+    ///@name Input and output\n+    ///@{\n+\n+    /// Turn back information as a string.\n+    std::string Info() const override\n+    {\n+        return \"ResidualBasedEliminationBuilderAndSolverWithConstraints\";\n+    }\n+\n+    /// Print information about this object.\n+    void PrintInfo(std::ostream& rOStream) const override\n+    {\n+        rOStream << Info();\n+    }\n+\n+    /// Print object's data.\n+    void PrintData(std::ostream& rOStream) const override\n+    {\n+        rOStream << Info();\n+    }\n+\n+    ///@}\n+    ///@name Friends\n+    ///@{\n+\n+    ///@}\n+protected:\n+    ///@name Protected static Member Variables\n+    ///@{\n+\n+    ///@}\n+    ///@name Protected member Variables\n+    ///@{\n+\n+    ///@}\n+    ///@name Protected Operators\n+    ///@{\n+\n+    ///@}\n+    ///@name Protected Operations\n+    ///@{\n+\n+    /**\n+    * @brief This method assembles the global relation matrix\n+    * @param rT The global relation matrix\n+    * @param rTransformationMatrix The local transformation contribution\n+    * @param rSlaveEquationId The equation id of the slave dofs\n+    * @param rMasterEquationId The equation id of the master dofs\n+    * @param rLockArray The lock of the dof\n+    */\n+    void AssembleRelationMatrix(\n+        TSystemMatrixType& rT,\n+        const LocalSystemMatrixType& rTransformationMatrix,\n+        const EquationIdVectorType& rSlaveEquationId,\n+        const EquationIdVectorType& rMasterEquationId\n+    #ifdef _OPENMP\n+        ,std::vector< omp_lock_t >& rLockArray\n+    #endif\n+        )\n+    {\n+        SizeType local_size_1 = rTransformationMatrix.size1();\n+        SizeType local_size_2 = rTransformationMatrix.size2();\n+\n+        for (IndexType i_local = 0; i_local < local_size_1; ++i_local) {\n+            IndexType i_global = rSlaveEquationId[i_local];\n+\n+            if (i_global < BaseType::mEquationSystemSize) {\n+            #ifdef _OPENMP\n+                omp_set_lock(&rLockArray[i_global]);\n+            #endif\n+                for (IndexType j_local = 0; j_local < local_size_2; ++j_local) {\n+                    IndexType j_global = mSolvableDoFReorder[rMasterEquationId[j_local]];\n+                    if (j_global < BaseType::mEquationSystemSize) {\n+                        rT(i_global, j_global) += rTransformationMatrix(i_local, j_local);\n+                    }\n+                }\n+            #ifdef _OPENMP\n+                omp_unset_lock(&rLockArray[i_global]);\n+            #endif\n+\n+            }\n+            //note that assembly on fixed rows is not performed here\n+        }\n+    }\n+\n+    /**\n+     * @brief This method construcs the relationship between the DoF\n+     * @param pScheme The integration scheme\n+     * @param rA The LHS of the system\n+     * @param rModelPart The model part which defines the problem\n+     */\n+    void ConstructMatrixStructure(\n+        typename TSchemeType::Pointer pScheme,\n+        TSystemMatrixType& rA,\n+        ModelPart& rModelPart\n+        ) override\n+    {\n+        if(rModelPart.MasterSlaveConstraints().size() > 0)\n+            ConstructMatrixStructureWithConstraints(pScheme, rA, rModelPart);\n+        else\n+            BaseType::ConstructMatrixStructure(pScheme, rA, rModelPart);\n+    }\n+\n+    /**\n+     * @brief The same methods as the base class but with constraints\n+     * @param pScheme The pointer to the integration scheme\n+     * @param rModelPart The model part to compute\n+     * @param rA The LHS matrix of the system of equations\n+     * @param rDx The vector of unkowns\n+     * @param rb The RHS vector of the system of equations\n+     */\n+    void BuildAndSolveWithConstraints(\n+        typename TSchemeType::Pointer pScheme,\n+        ModelPart& rModelPart,\n+        TSystemMatrixType& rA,\n+        TSystemVectorType& rDx,\n+        TSystemVectorType& rb\n+        )\n+    {\n+        KRATOS_TRY\n+\n+        Timer::Start(\"Build\");\n+\n+        Build(pScheme, rModelPart, rA, rb);\n+        rDx.resize(mDoFToSolveSystemSize, false);\n+\n+        Timer::Stop(\"Build\");\n+\n+        this->ApplyDirichletConditions(pScheme, rModelPart, rA, rDx, rb);\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", (this->GetEchoLevel() == 3)) <<\n+        \"Before the solution of the system\" << \"\\nSystem Matrix = \" << rA << \"\\nUnknowns vector = \" << rDx << \"\\nRHS vector = \" << rb << std::endl;\n+\n+        const double start_solve = OpenMPUtils::GetCurrentTime();\n+        Timer::Start(\"Solve\");\n+        this->SystemSolveWithPhysics(rA, rDx, rb, rModelPart);\n+        Timer::Stop(\"Solve\");\n+        const double stop_solve = OpenMPUtils::GetCurrentTime();\n+\n+        const double start_reconstruct_slaves = OpenMPUtils::GetCurrentTime();\n+        ReconstructSlaveSolutionAfterSolve(rModelPart, rA, rDx, rb);\n+\n+        const double stop_reconstruct_slaves = OpenMPUtils::GetCurrentTime();\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", (this->GetEchoLevel() >= 1 && rModelPart.GetCommunicator().MyPID() == 0)) << \"Reconstruct slaves time: \" << stop_reconstruct_slaves - start_reconstruct_slaves << std::endl;\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", (this->GetEchoLevel() >= 1 && rModelPart.GetCommunicator().MyPID() == 0)) << \"System solve time: \" << stop_solve - start_solve << std::endl;\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", (this->GetEchoLevel() == 3)) <<\n+        \"After the solution of the system\" << \"\\nSystem Matrix = \" << rA << \"\\nUnknowns vector = \" << rDx << \"\\nRHS vector = \" << rb << std::endl;\n+\n+        KRATOS_CATCH(\"\")\n+    }\n+\n+    /**\n+     * @brief This function is exactly same as the ConstructMatrixStructure() function in base class except that the function\n+     * @details Has the call to ApplyConstraints function call once the element and conditions compute their equation ids\n+     * @todo Move this method to a common class with block builder and solver with constraints\n+    */\n+    virtual void ConstructMatrixStructureWithConstraints(\n+        typename TSchemeType::Pointer pScheme,\n+        TSystemMatrixType& rA,\n+        ModelPart& rModelPart\n+        )\n+    {\n+        // Filling with zero the matrix (creating the structure)\n+        Timer::Start(\"MatrixStructure\");\n+\n+        // Getting the elements from the model\n+        const int number_of_elements = static_cast<int>(rModelPart.Elements().size());\n+\n+        // Getting the array of the conditions\n+        const int number_of_conditions = static_cast<int>(rModelPart.Conditions().size());\n+\n+        ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo();\n+        auto el_begin = rModelPart.ElementsBegin();\n+        auto cond_begin = rModelPart.ConditionsBegin();\n+\n+        const SizeType equation_size = BaseType::mEquationSystemSize;\n+\n+        std::vector<IndexSetType> indices(equation_size);\n+\n+        #pragma omp parallel for firstprivate(equation_size)\n+        for (int index = 0; index < static_cast<int>(equation_size); ++index)\n+            indices[index].reserve(40);\n+\n+        /// Definition of the eqautio id vector type\n+        EquationIdVectorType ids(3, 0);\n+\n+        #pragma omp parallel for firstprivate(number_of_elements, ids)\n+        for (int i_elem = 0; i_elem<number_of_elements; i_elem++) {\n+            auto it_elem = el_begin + i_elem;\n+            pScheme->EquationId( *(it_elem.base()), ids, r_current_process_info);\n+\n+            for (IndexType i = 0; i < ids.size(); ++i) {\n+                if (ids[i] < BaseType::mEquationSystemSize) {\n+                #ifdef _OPENMP\n+                    omp_set_lock(&BaseType::mlock_array[ids[i]]);\n+                #endif\n+                    auto& row_indices = indices[ids[i]];\n+                    for (auto it = ids.begin(); it != ids.end(); ++it) {\n+                        if (*it < BaseType::mEquationSystemSize)\n+                            row_indices.insert(*it);\n+                    }\n+                #ifdef _OPENMP\n+                    omp_unset_lock(&BaseType::mlock_array[ids[i]]);\n+                #endif\n+                }\n+            }\n+\n+        }\n+\n+        #pragma omp parallel for firstprivate(number_of_conditions, ids)\n+        for (int i_cond = 0; i_cond<number_of_conditions; ++i_cond) {\n+            auto it_cond = cond_begin + i_cond;\n+            pScheme->Condition_EquationId( *(it_cond.base()), ids, r_current_process_info);\n+            for (IndexType i = 0; i < ids.size(); ++i) {\n+                if (ids[i] < BaseType::mEquationSystemSize) {\n+                #ifdef _OPENMP\n+                    omp_set_lock(&BaseType::mlock_array[ids[i]]);\n+                #endif\n+                    auto& row_indices = indices[ids[i]];\n+                    for (auto it = ids.begin(); it != ids.end(); ++it) {\n+                        if (*it < BaseType::mEquationSystemSize)\n+                            row_indices.insert(*it);\n+                    }\n+                #ifdef _OPENMP\n+                    omp_unset_lock(&BaseType::mlock_array[ids[i]]);\n+                #endif\n+                }\n+            }\n+        }\n+\n+        EquationIdVectorType aux_ids(3, 0);\n+\n+        const int number_of_constraints = static_cast<int>(rModelPart.MasterSlaveConstraints().size());\n+        #pragma omp parallel for firstprivate(number_of_constraints, ids, aux_ids)\n+        for (int i_const = 0; i_const < number_of_constraints; ++i_const) {\n+            auto it_const = rModelPart.MasterSlaveConstraints().begin() + i_const;\n+            it_const->EquationIdVector(ids, aux_ids, r_current_process_info);\n+            for (IndexType i = 0; i < ids.size(); ++i) {\n+                if (ids[i] < BaseType::mEquationSystemSize) {\n+                #ifdef _OPENMP\n+                    omp_set_lock(&BaseType::mlock_array[ids[i]]);\n+                #endif\n+                    auto &row_indices = indices[ids[i]];\n+                    row_indices.insert(ids.begin(), ids.end());\n+                #ifdef _OPENMP\n+                    omp_unset_lock(&BaseType::mlock_array[ids[i]]);\n+                #endif\n+                }\n+            }\n+            for (IndexType i = 0; i < aux_ids.size(); ++i) {\n+                if (aux_ids[i] < BaseType::mEquationSystemSize) {\n+                #ifdef _OPENMP\n+                    omp_set_lock(&BaseType::mlock_array[aux_ids[i]]);\n+                #endif\n+                    auto &row_indices = indices[aux_ids[i]];\n+                    row_indices.insert(aux_ids.begin(), aux_ids.end());\n+                #ifdef _OPENMP\n+                    omp_unset_lock(&BaseType::mlock_array[aux_ids[i]]);\n+                #endif\n+                }\n+            }\n+        }\n+\n+        // Count the row sizes\n+        SizeType nnz = 0;\n+        for (IndexType i = 0; i < indices.size(); ++i)\n+            nnz += indices[i].size();\n+\n+        rA = CompressedMatrixType(indices.size(), indices.size(), nnz);\n+\n+        double *Avalues = rA.value_data().begin();\n+        IndexType *Arow_indices = rA.index1_data().begin();\n+        IndexType *Acol_indices = rA.index2_data().begin();\n+\n+        // Filling the index1 vector - DO NOT MAKE PARALLEL THE FOLLOWING LOOP!\n+        Arow_indices[0] = 0;\n+        for (int i = 0; i < static_cast<int>(rA.size1()); i++)\n+            Arow_indices[i + 1] = Arow_indices[i] + indices[i].size();\n+\n+        #pragma omp parallel for\n+        for (int i = 0; i < static_cast<int>(rA.size1()); ++i) {\n+            const IndexType row_begin = Arow_indices[i];\n+            const IndexType row_end = Arow_indices[i + 1];\n+            IndexType k = row_begin;\n+            for (auto it = indices[i].begin(); it != indices[i].end(); ++it) {\n+                Acol_indices[k] = *it;\n+                Avalues[k] = 0.0;\n+                k++;\n+            }\n+\n+            indices[i].clear(); //deallocating the memory\n+\n+            std::sort(&Acol_indices[row_begin], &Acol_indices[row_end]);\n+        }\n+\n+        rA.set_filled(indices.size() + 1, nnz);\n+\n+        Timer::Stop(\"MatrixStructure\");\n+    }\n+\n+    /**\n+     * @brief This function is exactly same as the ConstructMatrixStructure() function in base class except that the function has the call to ApplyConstraints function call once the element and conditions compute their equation slave_ids\n+     * @param pScheme The pointer to the integration scheme\n+     * @param rT The global relation matrix\n+     * @param rModelPart The model part to compute\n+    */\n+    virtual void ConstructRelationMatrixStructure(\n+        typename TSchemeType::Pointer pScheme,\n+        TSystemMatrixType& rT,\n+        ModelPart& rModelPart\n+        )\n+    {\n+        // Filling with zero the matrix (creating the structure)\n+        Timer::Start(\"RelationMatrixStructure\");\n+\n+        std::map<IndexType, bool> row_dof_indices; // Must be ordered to avoid problems filling the matrix\n+\n+        IndexSetType aux_master_indices;\n+        std::unordered_map<IndexType, IndexSetType> master_indices;\n+\n+        // We do a pair to know which DoF are pure master MPC\n+        typedef std::pair<IndexType, bool> PairIdBoolType;\n+\n+        // We build aux_master_indices from the inverse of mSlaveMasterDoFRelation\n+        for (auto& slave_set: mSlaveMasterDoFRelation) {\n+            auto& master_indices = slave_set.second;\n+            for (auto& master_id : master_indices) {\n+                aux_master_indices.insert(master_id);\n+            }\n+        }\n+        master_indices.reserve(mSlaveMasterDoFRelation.size());\n+\n+        // The set containing the solvable DoF that are not a master DoF\n+        typedef std::pair<IndexType, IndexSetType> IndexIndexSetPairType;\n+        for (auto& dof : BaseType::mDofSet) {\n+            const IndexType equation_id = dof.EquationId();\n+            if (equation_id < BaseType::mEquationSystemSize) {\n+                if (aux_master_indices.find(equation_id) != aux_master_indices.end()) {\n+                    row_dof_indices.insert(PairIdBoolType(equation_id, true));\n+                } else if (mSlaveMasterDoFRelation.find(equation_id) != mSlaveMasterDoFRelation.end()) {\n+                    row_dof_indices.insert(PairIdBoolType(equation_id, false));\n+                    master_indices.insert(IndexIndexSetPairType(equation_id, IndexSetType({})));\n+                } else {\n+                    row_dof_indices.insert(PairIdBoolType(equation_id, true));\n+                }\n+            }\n+        }\n+\n+        // Reserve on the indexes set\n+        for (auto& master_set : master_indices) {\n+            (master_set.second).reserve(3);\n+        }\n+\n+        // Clearing memory\n+        aux_master_indices.clear();\n+\n+        KRATOS_DEBUG_ERROR_IF_NOT(row_dof_indices.size() == BaseType::mEquationSystemSize) << \"Inconsistency in the dofs size: \" << row_dof_indices.size() << \"\\t vs \\t\" << BaseType::mEquationSystemSize << std::endl;\n+\n+        // The process info\n+        ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo();\n+\n+        /// Definition of the eqautio id vector type\n+        EquationIdVectorType ids(3, 0);\n+        EquationIdVectorType aux_ids(3, 0);\n+\n+        const int number_of_constraints = static_cast<int>(rModelPart.MasterSlaveConstraints().size());\n+        // TODO: OMP\n+        for (int i_const = 0; i_const < number_of_constraints; ++i_const) {\n+            auto it_const = rModelPart.MasterSlaveConstraints().begin() + i_const;\n+            it_const->EquationIdVector(ids, aux_ids, r_current_process_info);\n+            for (auto& slave_id : ids) {\n+                if (slave_id < BaseType::mEquationSystemSize) {\n+                    auto it_slave = mSlaveMasterDoFRelation.find(slave_id);\n+                    if (it_slave != mSlaveMasterDoFRelation.end()) {\n+                        auto& master_set = it_slave->second;\n+                        for (auto& master_id : aux_ids) {\n+                            if (master_id < BaseType::mEquationSystemSize) {\n+                                auto it_master = master_set.find(master_id);\n+                                if (it_master != master_set.end()) {\n+                                    auto &master_row_indices = master_indices[slave_id];\n+                                    master_row_indices.insert(mSolvableDoFReorder[master_id]);\n+                                }\n+                            }\n+                        }\n+                    }\n+                }\n+            }\n+        }\n+\n+        KRATOS_DEBUG_ERROR_IF_NOT(mSlaveMasterDoFRelation.size() == master_indices.size()) << \"Inconsistency in the master dofs size: \" << mSlaveMasterDoFRelation.size() << \"\\t vs \\t\" << master_indices.size() << std::endl;\n+\n+        // Count the row sizes\n+        SizeType nnz = 0;\n+        for (auto& to_solve : row_dof_indices) {\n+            if (to_solve.second) {\n+                ++nnz;\n+            } else {\n+                nnz += master_indices[to_solve.first].size();\n+            }\n+        }\n+\n+        rT = CompressedMatrixType(BaseType::mEquationSystemSize, mDoFToSolveSystemSize, nnz);\n+\n+        double *Tvalues = rT.value_data().begin();\n+        IndexType *Trow_indices = rT.index1_data().begin();\n+        IndexType *Tcol_indices = rT.index2_data().begin();\n+\n+        // Filling the index1 vector - DO NOT MAKE PARALLEL THE FOLLOWING LOOP!\n+        Trow_indices[0] = 0;\n+        IndexType counter = 0;\n+        for (auto& to_solve : row_dof_indices) {\n+            if (to_solve.second) {\n+                Trow_indices[counter + 1] = Trow_indices[counter] + 1;\n+            } else {\n+                Trow_indices[counter + 1] = Trow_indices[counter] + master_indices[to_solve.first].size();\n+            }\n+            ++counter;\n+        }\n+\n+        KRATOS_DEBUG_ERROR_IF_NOT(Trow_indices[counter] == nnz) << \"Nonzero values does not coincide with the row index definition\" << std::endl;\n+\n+        counter = 0;\n+        // TODO: OMP\n+        for (auto& to_solve : row_dof_indices) {\n+            const IndexType row_begin = Trow_indices[counter];\n+            const IndexType row_end = Trow_indices[counter + 1];\n+\n+            IndexType k = row_begin;\n+            if (to_solve.second) {\n+                Tcol_indices[k] = mSolvableDoFReorder[to_solve.first];\n+                Tvalues[k] = 1.0;\n+            } else {\n+                for (auto& index : master_indices[to_solve.first]) {\n+                    Tcol_indices[k] = index;\n+                    Tvalues[k] = 0.0;\n+                    k++;\n+                }\n+                master_indices[to_solve.first].clear(); //deallocating the memory\n+            }\n+\n+            std::sort(&Tcol_indices[row_begin], &Tcol_indices[row_end]);\n+\n+            ++counter;\n+        }\n+\n+        rT.set_filled(BaseType::mEquationSystemSize + 1, nnz);\n+\n+        Timer::Stop(\"RelationMatrixStructure\");\n+    }\n+\n+    /**\n+     * @brief This function is exactly same as the Build() function in base class except that the function\n+     * @details It has the call to ApplyConstraints function call once the LHS or RHS are computed by elements and conditions\n+     */\n+    void BuildWithConstraints(\n+        typename TSchemeType::Pointer pScheme,\n+        ModelPart& rModelPart,\n+        TSystemMatrixType& rA,\n+        TSystemVectorType& rb\n+        )\n+    {\n+        KRATOS_TRY\n+\n+        // We build the original system\n+        BaseType::Build(pScheme, rModelPart, rA, rb);\n+\n+        // Assemble the constraints\n+        const double start_build = OpenMPUtils::GetCurrentTime();\n+\n+        // We build the global T matrix\n+        TSystemMatrixType& rTMatrix = *mpTMatrix;\n+\n+        // We compute only once (or if cleared)\n+        if (BaseType::GetReshapeMatrixFlag() || mCleared) {\n+            mCleared = false;\n+\n+            // Contributions to the system\n+            LocalSystemMatrixType transformation_matrix = LocalSystemMatrixType(0, 0);\n+            LocalSystemVectorType constant_vector = LocalSystemVectorType(0);\n+\n+            // Vector containing the localization in the system of the different terms\n+            EquationIdVectorType slave_equation_id, master_equation_id;\n+\n+            // The current process info\n+            ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo();\n+\n+            const int number_of_constraints = static_cast<int>(rModelPart.MasterSlaveConstraints().size());\n+            #pragma omp parallel for firstprivate(number_of_constraints, transformation_matrix, constant_vector, slave_equation_id)\n+            for (int i_const = 0; i_const < number_of_constraints; ++i_const) {\n+                auto it_const = rModelPart.MasterSlaveConstraints().begin() + i_const;\n+\n+                // Detect if the constraint is active or not. If the user did not make any choice the constraint\n+                // It is active by default\n+                bool constraint_is_active = true;\n+                if (it_const->IsDefined(ACTIVE))\n+                    constraint_is_active = it_const->Is(ACTIVE);\n+\n+                if (constraint_is_active) {\n+                    it_const->CalculateLocalSystem(transformation_matrix, constant_vector, r_current_process_info);\n+\n+                    it_const->EquationIdVector(slave_equation_id, master_equation_id, r_current_process_info);\n+\n+                    // Assemble the constraint contribution\n+                #ifdef _OPENMP\n+                    AssembleRelationMatrix(rTMatrix, transformation_matrix, slave_equation_id, master_equation_id, BaseType::mlock_array);\n+                #else\n+                    AssembleRelationMatrix(rTMatrix, transformation_matrix, slave_equation_id, master_equation_id);\n+                #endif\n+                }\n+            }\n+        }\n+\n+        // We compute the transposed matrix of the global relation matrix\n+        TSystemMatrixType T_transpose_matrix(mDoFToSolveSystemSize, BaseType::mEquationSystemSize);\n+        SparseMatrixMultiplicationUtility::TransposeMatrix<TSystemMatrixType, TSystemMatrixType>(T_transpose_matrix, rTMatrix, 1.0);\n+\n+        // The auxiliar matrix to store the intermediate matrix multiplication\n+        TSystemMatrixType auxiliar_A_matrix(mDoFToSolveSystemSize, BaseType::mEquationSystemSize);\n+        SparseMatrixMultiplicationUtility::MatrixMultiplication(T_transpose_matrix, rA, auxiliar_A_matrix);\n+\n+        // We resize of system of equations\n+        rA.resize(mDoFToSolveSystemSize, mDoFToSolveSystemSize, false);\n+        VectorType rb_copy(rb);\n+        rb.resize(mDoFToSolveSystemSize, false);\n+\n+        // Final multiplication\n+        SparseMatrixMultiplicationUtility::MatrixMultiplication(auxiliar_A_matrix, rTMatrix, rA);\n+        TSparseSpace::Mult(T_transpose_matrix, rb_copy, rb);\n+\n+        // TODO: The proper way to include the constants os in the RHS as T^t(f - A * c) -> Include the constants once the problem of the delta is solved\n+\n+        const double stop_build = OpenMPUtils::GetCurrentTime();\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", (this->GetEchoLevel() >= 1 && rModelPart.GetCommunicator().MyPID() == 0)) << \"Constraint relation build time and multiplication: \" << stop_build - start_build << std::endl;\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", (this->GetEchoLevel() > 2 && rModelPart.GetCommunicator().MyPID() == 0)) << \"Finished parallel building with constraints\" << std::endl;\n+\n+        KRATOS_CATCH(\"\")\n+    }\n+\n+    /**\n+     * @brief This method resize and initializes the system of euqations\n+     * @details Additionally what is done in the base class the constraints are initialized\n+     * @param pA The pointer to the LHS matrix\n+     * @param pDx The pointer to the vector of Unknowns\n+     * @param pb The pointer to the RHS vector\n+     * @param rModelPart The model part to be computed\n+     */\n+    void ResizeAndInitializeVectors(\n+        typename TSchemeType::Pointer pScheme,\n+        TSystemMatrixPointerType& pA,\n+        TSystemVectorPointerType& pDx,\n+        TSystemVectorPointerType& pb,\n+        ModelPart& rModelPart\n+        ) override\n+    {\n+        // We resize the basic system\n+        BaseType::ResizeAndInitializeVectors(pScheme, pA, pDx, pb, rModelPart);\n+\n+        // Now we resize the constraint system\n+        if(rModelPart.MasterSlaveConstraints().size() > 0) {\n+            if (mpTMatrix == NULL) { // If the pointer is not initialized initialize it to an empty matrix\n+                TSystemMatrixPointerType pNewT = TSystemMatrixPointerType(new TSystemMatrixType(0, 0));\n+                mpTMatrix.swap(pNewT);\n+            }\n+\n+            TSystemMatrixType& rTMatrix = *mpTMatrix;\n+\n+            // Resizing the system vectors and matrix\n+            if (rTMatrix.size1() == 0 || BaseType::GetReshapeMatrixFlag() || mCleared) { // If the matrix is not initialized\n+                rTMatrix.resize(BaseType::mEquationSystemSize, mDoFToSolveSystemSize, false);\n+                ConstructRelationMatrixStructure(pScheme, rTMatrix, rModelPart);\n+            } else {\n+                if (rTMatrix.size1() != BaseType::mEquationSystemSize || rTMatrix.size2() != mDoFToSolveSystemSize) {\n+                    KRATOS_ERROR <<\"The equation system size has changed during the simulation. This is not permited.\"<<std::endl;\n+                    rTMatrix.resize(BaseType::mEquationSystemSize, mDoFToSolveSystemSize, true);\n+                    ConstructRelationMatrixStructure(pScheme, rTMatrix, rModelPart);\n+                }\n+            }\n+        }\n+    }\n+\n+    /**\n+     * @brief This function is intended to be called at the end of the solution step to clean up memory storage not needed\n+     */\n+    void Clear() override\n+    {\n+        BaseType::Clear();\n+\n+        mDoFToSolveSet = DofsArrayType();\n+        mSolvableDoFReorder.clear();\n+        mSlaveMasterDoFRelation.clear();\n+\n+        // Set the flag\n+        mCleared = true;\n+\n+        KRATOS_INFO_IF(\"ResidualBasedEliminationBuilderAndSolverWithConstraints\", this->GetEchoLevel() > 1) << \"Clear Function called\" << std::endl;\n+    }\n+\n+    ///@}\n+    ///@name Protected  Access\n+    ///@{\n+\n+    ///@}\n+    ///@name Protected Inquiry\n+    ///@{\n+\n+    ///@}\n+    ///@name Protected LifeCycle\n+    ///@{\n+\n+    ///@}\n+\n+private:\n+    ///@name Static Member Variables\n+    ///@{\n+\n+    ///@}\n+    ///@name Member Variables\n+    ///@{\n+\n+    TSystemMatrixPointerType mpTMatrix = NULL; /// This is matrix containing the global relation for the constraints\n+\n+    DofsArrayType mDoFToSolveSet;              /// The set containing the solvable DoF of the system\n+\n+    SizeType mDoFToSolveSystemSize = 0;        /// Number of degrees of freedom of the problem to actually be solved\n+\n+    bool mCleared = true; /// If the system has been reseted\n+\n+    std::unordered_map<IndexType, IndexType> mSolvableDoFReorder; /// The correlation between the global total DoF order and the solvable DoF order\n+    std::unordered_map<IndexType, IndexSetType> mSlaveMasterDoFRelation; /// The relation between the slave and the master DoFs\n+\n+    ///@}\n+    ///@name Private Operators\n+    ///@{\n+\n+    ///@}\n+    ///@name Private Operations\n+    ///@{\n+\n+    /**\n+     * @brief This method computes the equivalent coounter part of the SetUpSystem when using constraints\n+     * @param rModelPart The model part of the problem to solve\n+     */\n+    void SetUpSystemWithConstraints(ModelPart& rModelPart)\n+    {\n+        KRATOS_TRY\n+\n+        // First we set up the system of equations without constraints\n+        BaseType::SetUpSystem(rModelPart);\n+\n+        /// A pair of Ids\n+        typedef std::pair<IndexType, IndexType> IdPairType;\n+\n+        // Add the computation of the global ids of the solvable dofs\n+        mSolvableDoFReorder.reserve(mDoFToSolveSystemSize);\n+        IndexType counter = 0;\n+        for (auto& dof : BaseType::mDofSet) {\n+            if (dof.EquationId() < BaseType::mEquationSystemSize) {\n+                auto it = mDoFToSolveSet.find(dof);\n+                if (it != mDoFToSolveSet.end()) {\n+                    mSolvableDoFReorder.insert(IdPairType(dof.EquationId(), counter));","path":"kratos/solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver_with_constraints.h","position":1113,"original_position":1137,"commit_id":"2f99f1ed5f8dd394091af0382c0eebe7b6790887","original_commit_id":"aa9c1b2dba30a119d5f2ee804cab975e73eaae23","user":{"login":"loumalouomega","id":19991680,"node_id":"MDQ6VXNlcjE5OTkxNjgw","avatar_url":"https://avatars2.githubusercontent.com/u/19991680?v=4","gravatar_id":"","url":"https://api.github.com/users/loumalouomega","html_url":"https://github.com/loumalouomega","followers_url":"https://api.github.com/users/loumalouomega/followers","following_url":"https://api.github.com/users/loumalouomega/following{/other_user}","gists_url":"https://api.github.com/users/loumalouomega/gists{/gist_id}","starred_url":"https://api.github.com/users/loumalouomega/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/loumalouomega/subscriptions","organizations_url":"https://api.github.com/users/loumalouomega/orgs","repos_url":"https://api.github.com/users/loumalouomega/repos","events_url":"https://api.github.com/users/loumalouomega/events{/privacy}","received_events_url":"https://api.github.com/users/loumalouomega/received_events","type":"User","site_admin":false},"body":"@RiccardoRossi I am unable to make this work with just a vector","created_at":"2018-11-06T08:01:22Z","updated_at":"2018-11-06T08:01:23Z","html_url":"https://github.com/KratosMultiphysics/Kratos/pull/3249#discussion_r231025982","pull_request_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/3249","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/comments/231025982"},"html":{"href":"https://github.com/KratosMultiphysics/Kratos/pull/3249#discussion_r231025982"},"pull_request":{"href":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/3249"}},"in_reply_to_id":230580889},"pull_request":{"url":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/3249","id":228112569,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI4MTEyNTY5","html_url":"https://github.com/KratosMultiphysics/Kratos/pull/3249","diff_url":"https://github.com/KratosMultiphysics/Kratos/pull/3249.diff","patch_url":"https://github.com/KratosMultiphysics/Kratos/pull/3249.patch","issue_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues/3249","number":3249,"state":"open","locked":false,"title":"[Core] Adding elimination builder and solver with constraints","user":{"login":"loumalouomega","id":19991680,"node_id":"MDQ6VXNlcjE5OTkxNjgw","avatar_url":"https://avatars2.githubusercontent.com/u/19991680?v=4","gravatar_id":"","url":"https://api.github.com/users/loumalouomega","html_url":"https://github.com/loumalouomega","followers_url":"https://api.github.com/users/loumalouomega/followers","following_url":"https://api.github.com/users/loumalouomega/following{/other_user}","gists_url":"https://api.github.com/users/loumalouomega/gists{/gist_id}","starred_url":"https://api.github.com/users/loumalouomega/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/loumalouomega/subscriptions","organizations_url":"https://api.github.com/users/loumalouomega/orgs","repos_url":"https://api.github.com/users/loumalouomega/repos","events_url":"https://api.github.com/users/loumalouomega/events{/privacy}","received_events_url":"https://api.github.com/users/loumalouomega/received_events","type":"User","site_admin":false},"body":"Fixes #3189\n\nReduces considerably the solving time of a general problem because solves the reduced system (but this means that you cannot use the AMGCL solver, but for any direct solver the time consumed solving the system is drop) \n\nI have questions how to integrate the constants (not algebraically), I mean how to consider only once (because we solve in residual form and we are computing increments)\n\nI was thinking into take the current solution of the dof and compute the increment of constant, but I have doubts.\n\nRequires #3236\n\nRegards","created_at":"2018-11-03T11:02:58Z","updated_at":"2018-11-06T08:01:23Z","closed_at":null,"merged_at":null,"merge_commit_sha":"65296b599bce21bdb4b17f586cb10cabd59a63db","assignee":null,"assignees":[],"requested_reviewers":[{"login":"adityaghantasala","id":2531316,"node_id":"MDQ6VXNlcjI1MzEzMTY=","avatar_url":"https://avatars1.githubusercontent.com/u/2531316?v=4","gravatar_id":"","url":"https://api.github.com/users/adityaghantasala","html_url":"https://github.com/adityaghantasala","followers_url":"https://api.github.com/users/adityaghantasala/followers","following_url":"https://api.github.com/users/adityaghantasala/following{/other_user}","gists_url":"https://api.github.com/users/adityaghantasala/gists{/gist_id}","starred_url":"https://api.github.com/users/adityaghantasala/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adityaghantasala/subscriptions","organizations_url":"https://api.github.com/users/adityaghantasala/orgs","repos_url":"https://api.github.com/users/adityaghantasala/repos","events_url":"https://api.github.com/users/adityaghantasala/events{/privacy}","received_events_url":"https://api.github.com/users/adityaghantasala/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":539268248,"node_id":"MDU6TGFiZWw1MzkyNjgyNDg=","url":"https://api.github.com/repos/KratosMultiphysics/Kratos/labels/Applications","name":"Applications","color":"0052cc","default":false},{"id":538395921,"node_id":"MDU6TGFiZWw1MzgzOTU5MjE=","url":"https://api.github.com/repos/KratosMultiphysics/Kratos/labels/Enhancement","name":"Enhancement","color":"77d86e","default":false},{"id":539268135,"node_id":"MDU6TGFiZWw1MzkyNjgxMzU=","url":"https://api.github.com/repos/KratosMultiphysics/Kratos/labels/Kratos%20Core","name":"Kratos Core","color":"0052cc","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/3249/commits","review_comments_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/3249/comments","review_comment_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/comments{/number}","comments_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues/3249/comments","statuses_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/statuses/2f99f1ed5f8dd394091af0382c0eebe7b6790887","head":{"label":"KratosMultiphysics:core/elimination-builder-and-solver-with-constraints","ref":"core/elimination-builder-and-solver-with-constraints","sha":"2f99f1ed5f8dd394091af0382c0eebe7b6790887","user":{"login":"KratosMultiphysics","id":24840449,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI0ODQwNDQ5","avatar_url":"https://avatars1.githubusercontent.com/u/24840449?v=4","gravatar_id":"","url":"https://api.github.com/users/KratosMultiphysics","html_url":"https://github.com/KratosMultiphysics","followers_url":"https://api.github.com/users/KratosMultiphysics/followers","following_url":"https://api.github.com/users/KratosMultiphysics/following{/other_user}","gists_url":"https://api.github.com/users/KratosMultiphysics/gists{/gist_id}","starred_url":"https://api.github.com/users/KratosMultiphysics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KratosMultiphysics/subscriptions","organizations_url":"https://api.github.com/users/KratosMultiphysics/orgs","repos_url":"https://api.github.com/users/KratosMultiphysics/repos","events_url":"https://api.github.com/users/KratosMultiphysics/events{/privacy}","received_events_url":"https://api.github.com/users/KratosMultiphysics/received_events","type":"Organization","site_admin":false},"repo":{"id":81815495,"node_id":"MDEwOlJlcG9zaXRvcnk4MTgxNTQ5NQ==","name":"Kratos","full_name":"KratosMultiphysics/Kratos","private":false,"owner":{"login":"KratosMultiphysics","id":24840449,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI0ODQwNDQ5","avatar_url":"https://avatars1.githubusercontent.com/u/24840449?v=4","gravatar_id":"","url":"https://api.github.com/users/KratosMultiphysics","html_url":"https://github.com/KratosMultiphysics","followers_url":"https://api.github.com/users/KratosMultiphysics/followers","following_url":"https://api.github.com/users/KratosMultiphysics/following{/other_user}","gists_url":"https://api.github.com/users/KratosMultiphysics/gists{/gist_id}","starred_url":"https://api.github.com/users/KratosMultiphysics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KratosMultiphysics/subscriptions","organizations_url":"https://api.github.com/users/KratosMultiphysics/orgs","repos_url":"https://api.github.com/users/KratosMultiphysics/repos","events_url":"https://api.github.com/users/KratosMultiphysics/events{/privacy}","received_events_url":"https://api.github.com/users/KratosMultiphysics/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/KratosMultiphysics/Kratos","description":"Kratos Multiphysics (A.K.A Kratos) is a framework for building parallel multi-disciplinary simulation software. Modularity, extensibility and HPC are the main objectives. Kratos has BSD license and is written in C++ with extensive Python interface.","fork":false,"url":"https://api.github.com/repos/KratosMultiphysics/Kratos","forks_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/forks","keys_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/teams","hooks_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/hooks","issue_events_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues/events{/number}","events_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/events","assignees_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/assignees{/user}","branches_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/branches{/branch}","tags_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/tags","blobs_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/refs{/sha}","trees_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/statuses/{sha}","languages_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/languages","stargazers_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/stargazers","contributors_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/contributors","subscribers_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/subscribers","subscription_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/subscription","commits_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/commits{/sha}","git_commits_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/commits{/sha}","comments_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/comments{/number}","issue_comment_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues/comments{/number}","contents_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/contents/{+path}","compare_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/merges","archive_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/downloads","issues_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues{/number}","pulls_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls{/number}","milestones_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/milestones{/number}","notifications_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/labels{/name}","releases_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/releases{/id}","deployments_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/deployments","created_at":"2017-02-13T10:58:24Z","updated_at":"2018-11-06T08:00:51Z","pushed_at":"2018-11-06T08:00:44Z","git_url":"git://github.com/KratosMultiphysics/Kratos.git","ssh_url":"git@github.com:KratosMultiphysics/Kratos.git","clone_url":"https://github.com/KratosMultiphysics/Kratos.git","svn_url":"https://github.com/KratosMultiphysics/Kratos","homepage":"http://www.cimne.com/kratos/","size":1254010,"stargazers_count":215,"watchers_count":215,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":45,"mirror_url":null,"archived":false,"open_issues_count":178,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":45,"open_issues":178,"watchers":215,"default_branch":"master"}},"base":{"label":"KratosMultiphysics:master","ref":"master","sha":"60b6b3a672cc0af703b9cef45bcd040f794ede3c","user":{"login":"KratosMultiphysics","id":24840449,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI0ODQwNDQ5","avatar_url":"https://avatars1.githubusercontent.com/u/24840449?v=4","gravatar_id":"","url":"https://api.github.com/users/KratosMultiphysics","html_url":"https://github.com/KratosMultiphysics","followers_url":"https://api.github.com/users/KratosMultiphysics/followers","following_url":"https://api.github.com/users/KratosMultiphysics/following{/other_user}","gists_url":"https://api.github.com/users/KratosMultiphysics/gists{/gist_id}","starred_url":"https://api.github.com/users/KratosMultiphysics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KratosMultiphysics/subscriptions","organizations_url":"https://api.github.com/users/KratosMultiphysics/orgs","repos_url":"https://api.github.com/users/KratosMultiphysics/repos","events_url":"https://api.github.com/users/KratosMultiphysics/events{/privacy}","received_events_url":"https://api.github.com/users/KratosMultiphysics/received_events","type":"Organization","site_admin":false},"repo":{"id":81815495,"node_id":"MDEwOlJlcG9zaXRvcnk4MTgxNTQ5NQ==","name":"Kratos","full_name":"KratosMultiphysics/Kratos","private":false,"owner":{"login":"KratosMultiphysics","id":24840449,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI0ODQwNDQ5","avatar_url":"https://avatars1.githubusercontent.com/u/24840449?v=4","gravatar_id":"","url":"https://api.github.com/users/KratosMultiphysics","html_url":"https://github.com/KratosMultiphysics","followers_url":"https://api.github.com/users/KratosMultiphysics/followers","following_url":"https://api.github.com/users/KratosMultiphysics/following{/other_user}","gists_url":"https://api.github.com/users/KratosMultiphysics/gists{/gist_id}","starred_url":"https://api.github.com/users/KratosMultiphysics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KratosMultiphysics/subscriptions","organizations_url":"https://api.github.com/users/KratosMultiphysics/orgs","repos_url":"https://api.github.com/users/KratosMultiphysics/repos","events_url":"https://api.github.com/users/KratosMultiphysics/events{/privacy}","received_events_url":"https://api.github.com/users/KratosMultiphysics/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/KratosMultiphysics/Kratos","description":"Kratos Multiphysics (A.K.A Kratos) is a framework for building parallel multi-disciplinary simulation software. Modularity, extensibility and HPC are the main objectives. Kratos has BSD license and is written in C++ with extensive Python interface.","fork":false,"url":"https://api.github.com/repos/KratosMultiphysics/Kratos","forks_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/forks","keys_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/teams","hooks_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/hooks","issue_events_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues/events{/number}","events_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/events","assignees_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/assignees{/user}","branches_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/branches{/branch}","tags_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/tags","blobs_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/refs{/sha}","trees_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/statuses/{sha}","languages_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/languages","stargazers_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/stargazers","contributors_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/contributors","subscribers_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/subscribers","subscription_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/subscription","commits_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/commits{/sha}","git_commits_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/git/commits{/sha}","comments_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/comments{/number}","issue_comment_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues/comments{/number}","contents_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/contents/{+path}","compare_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/merges","archive_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/downloads","issues_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues{/number}","pulls_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls{/number}","milestones_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/milestones{/number}","notifications_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/labels{/name}","releases_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/releases{/id}","deployments_url":"https://api.github.com/repos/KratosMultiphysics/Kratos/deployments","created_at":"2017-02-13T10:58:24Z","updated_at":"2018-11-06T08:00:51Z","pushed_at":"2018-11-06T08:00:44Z","git_url":"git://github.com/KratosMultiphysics/Kratos.git","ssh_url":"git@github.com:KratosMultiphysics/Kratos.git","clone_url":"https://github.com/KratosMultiphysics/Kratos.git","svn_url":"https://github.com/KratosMultiphysics/Kratos","homepage":"http://www.cimne.com/kratos/","size":1254010,"stargazers_count":215,"watchers_count":215,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":45,"mirror_url":null,"archived":false,"open_issues_count":178,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":45,"open_issues":178,"watchers":215,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/3249"},"html":{"href":"https://github.com/KratosMultiphysics/Kratos/pull/3249"},"issue":{"href":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues/3249"},"comments":{"href":"https://api.github.com/repos/KratosMultiphysics/Kratos/issues/3249/comments"},"review_comments":{"href":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/3249/comments"},"review_comment":{"href":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/KratosMultiphysics/Kratos/pulls/3249/commits"},"statuses":{"href":"https://api.github.com/repos/KratosMultiphysics/Kratos/statuses/2f99f1ed5f8dd394091af0382c0eebe7b6790887"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"loumalouomega"}}