Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kratos lspg hrom #11569

Merged
merged 26 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ed642fc
Merge branch 'master' into Kratos_LSPG_HROM
SADPR Sep 15, 2023
1127c89
SetHRomComputingModelPartWithNeighbours function
SADPR Sep 15, 2023
368a61e
GetProjectedResidualsOntoPhiJ
SADPR Sep 15, 2023
8898c68
Declaration in source file.
SADPR Sep 15, 2023
bcbfd2d
Exporting to python
SADPR Sep 15, 2023
d35893e
Allowing lspg in hrom utilities.
SADPR Sep 15, 2023
d53cd03
Adding number of righ rom basis modes
SADPR Sep 15, 2023
d23c595
GetRightROMBasis spelling error.
SADPR Sep 15, 2023
4a02480
Add BuildWithComplementaryMesh and FindNeighbouringElementsAndConditions
SADPR Sep 15, 2023
2b758ed
Overriding SetUpDofSet
SADPR Sep 15, 2023
eaad11b
BaseType
SADPR Sep 15, 2023
7820666
Compiled with segmentation fault (even with 1 thread).
SADPR Sep 15, 2023
f4b9b42
Working.
SADPR Sep 15, 2023
3f66285
Changing PhiJ to JPhi
SADPR Sep 18, 2023
e4813fb
JPhi typo.
SADPR Sep 19, 2023
cdf2276
Working LSPG HROM, cleaned.
SADPR Sep 19, 2023
50c2997
Adapting rom_manager.
SADPR Sep 19, 2023
87b78ff
Added test.
SADPR Sep 19, 2023
8231ffc
Override missing
SADPR Sep 19, 2023
a04b464
"Introduce HROM LSPG enhancements and fix clang compilation issues"
SADPR Sep 19, 2023
3ba8a71
Trailing whitespace.
SADPR Sep 21, 2023
cb2d335
Avoiding repetitive code.
SADPR Sep 21, 2023
4ccce65
Merge branch 'master' into Kratos_LSPG_HROM
Rbravo555 Sep 22, 2023
afef1ed
Added code for launching LSPG-HROM simulations with RomManager
Rbravo555 Sep 26, 2023
c51f803
trailing whitespaces
Rbravo555 Sep 26, 2023
d07c9eb
Merge branch 'master' into Kratos_LSPG_HROM
Rbravo555 Sep 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ void AddCustomUtilitiesToPython(pybind11::module& m)
.def(init<ModelPart&, Parameters, BaseSchemeType::Pointer>()) //
.def("GetProjectedResidualsOntoPhi",&RomResidualsUtility::GetProjectedResidualsOntoPhi) //
.def("GetProjectedResidualsOntoPsi",&RomResidualsUtility::GetProjectedResidualsOntoPsi) //
.def("GetProjectedResidualsOntoJPhi",&RomResidualsUtility::GetProjectedResidualsOntoJPhi) //
;

class_<RomAuxiliaryUtilities>(m, "RomAuxiliaryUtilities")
.def_static("SetHRomComputingModelPart", &RomAuxiliaryUtilities::SetHRomComputingModelPart)
.def_static("SetHRomComputingModelPartWithNeighbours", &RomAuxiliaryUtilities::SetHRomComputingModelPartWithNeighbours)
.def_static("SetHRomVolumetricVisualizationModelPart", &RomAuxiliaryUtilities::SetHRomVolumetricVisualizationModelPart)
.def_static("GetHRomConditionParentsIds", &RomAuxiliaryUtilities::GetHRomConditionParentsIds)
.def_static("GetNodalNeighbouringElementIdsNotInHRom", &RomAuxiliaryUtilities::GetNodalNeighbouringElementIdsNotInHRom)
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,170 @@ void RomAuxiliaryUtilities::RecursiveHRomModelPartCreation(
}
}

void RomAuxiliaryUtilities::SetHRomComputingModelPartWithNeighbours(
const Parameters HRomWeights,
ModelPart& rOriginModelPart,
ModelPart& rHRomComputingModelPart)
{
// Ensure that the provided destination model part is empty
rHRomComputingModelPart.Clear();

// Auxiliary containers to save the entities involved in the HROM mesh
NodesPointerSetType hrom_nodes_set;
std::vector<Element::Pointer> hrom_elems_vect;
std::vector<Condition::Pointer> hrom_conds_vect;

const auto& r_elem_weights = HRomWeights["Elements"];
const auto& r_cond_weights = HRomWeights["Conditions"];

hrom_elems_vect.reserve(rOriginModelPart.NumberOfElements());
hrom_conds_vect.reserve(rOriginModelPart.NumberOfConditions());

FindGlobalNodalEntityNeighboursProcess<ModelPart::ElementsContainerType> find_nodal_elements_neighbours_process(rOriginModelPart);
find_nodal_elements_neighbours_process.Execute();
FindGlobalNodalEntityNeighboursProcess<ModelPart::ConditionsContainerType> find_nodal_conditions_neighbours_process(rOriginModelPart);
find_nodal_conditions_neighbours_process.Execute();

for (auto it = r_elem_weights.begin(); it != r_elem_weights.end(); ++it) {
// Get element from origin mesh
const IndexType elem_id = stoi(it.name());
const auto p_elem = rOriginModelPart.pGetElement(elem_id + 1);

// Add the element to the auxiliary container and to the main HROM model part
if(std::find(hrom_elems_vect.begin(), hrom_elems_vect.end(), p_elem) == hrom_elems_vect.end()) {
hrom_elems_vect.push_back(p_elem);
rHRomComputingModelPart.AddElement(p_elem);
}

// Add the element nodes to the auxiliary set and to the main HROM model part
const auto& r_geom = p_elem->GetGeometry();
const SizeType n_nodes = r_geom.PointsNumber();
for (IndexType i_node = 0; i_node < n_nodes; ++i_node) {
NodeType::Pointer p_node = r_geom(i_node);
hrom_nodes_set.insert(hrom_nodes_set.end(), p_node);
rHRomComputingModelPart.AddNode(p_node);

// Get the neighbor elements from each node and add them to the model part
for (auto& neighbor_elem : p_node->GetValue(NEIGHBOUR_ELEMENTS)) {
Kratos::Element::Pointer p_neighbor_elem = &neighbor_elem;
// Be careful to not add an element that is already in the model part.
// For this, we will check if the element is already in our vector of elements.
if(std::find(hrom_elems_vect.begin(), hrom_elems_vect.end(), p_neighbor_elem) == hrom_elems_vect.end()) {
hrom_elems_vect.push_back(p_neighbor_elem);
rHRomComputingModelPart.AddElement(p_neighbor_elem);

// Add the nodes of the neighboring element to the model part
const auto& neighbor_r_geom = p_neighbor_elem->GetGeometry();
const SizeType neighbor_n_nodes = neighbor_r_geom.PointsNumber();
for (IndexType i_neighbor_node = 0; i_neighbor_node < neighbor_n_nodes; ++i_neighbor_node) {
NodeType::Pointer p_neighbor_node = neighbor_r_geom(i_neighbor_node);
hrom_nodes_set.insert(hrom_nodes_set.end(), p_neighbor_node);
rHRomComputingModelPart.AddNode(p_neighbor_node);
}
}
}

// Get the neighbor conditions from each node and add them to the model part
for (auto& neighbor_cond : p_node->GetValue(NEIGHBOUR_CONDITIONS)) {
Kratos::Condition::Pointer p_neighbor_cond = &neighbor_cond;
// Be careful to not add a condition that is already in the model part.
// For this, we will check if the condition is already in our vector of conditions.
if(std::find(hrom_conds_vect.begin(), hrom_conds_vect.end(), p_neighbor_cond) == hrom_conds_vect.end()) {
hrom_conds_vect.push_back(p_neighbor_cond);
rHRomComputingModelPart.AddCondition(p_neighbor_cond);

// Add the nodes of the neighboring condition to the model part
const auto& neighbor_r_geom = p_neighbor_cond->GetGeometry();
const SizeType neighbor_n_nodes = neighbor_r_geom.PointsNumber();
for (IndexType i_neighbor_node = 0; i_neighbor_node < neighbor_n_nodes; ++i_neighbor_node) {
NodeType::Pointer p_neighbor_node = neighbor_r_geom(i_neighbor_node);
hrom_nodes_set.insert(hrom_nodes_set.end(), p_neighbor_node);
rHRomComputingModelPart.AddNode(p_neighbor_node);
}
}
}
}
}

for (auto it = r_cond_weights.begin(); it != r_cond_weights.end(); ++it) {
// Get the condition from origin mesh
const IndexType cond_id = stoi(it.name());
auto p_cond = rOriginModelPart.pGetCondition(cond_id + 1);

// Add the condition to the auxiliary container and to the main HROM model part
if(std::find(hrom_conds_vect.begin(), hrom_conds_vect.end(), p_cond) == hrom_conds_vect.end()) {
hrom_conds_vect.push_back(p_cond);
rHRomComputingModelPart.AddCondition(p_cond);
}

// Add the condition nodes to the auxiliary set and to the main HROM model part
const auto& r_geom = p_cond->GetGeometry();
const SizeType n_nodes = r_geom.PointsNumber();
for (IndexType i_node = 0; i_node < n_nodes; ++i_node) {
auto p_node = r_geom(i_node);
hrom_nodes_set.insert(hrom_nodes_set.end(), p_node);
rHRomComputingModelPart.AddNode(p_node);

// Get the neighbor elements from each node and add them to the model part
for (auto& neighbor_elem : p_node->GetValue(NEIGHBOUR_ELEMENTS)) {
Kratos::Element::Pointer p_neighbor_elem = &neighbor_elem;
// Be careful to not add an element that is already in the model part.
// For this, we will check if the element is already in our vector of elements.
if(std::find(hrom_elems_vect.begin(), hrom_elems_vect.end(), p_neighbor_elem) == hrom_elems_vect.end()) {
hrom_elems_vect.push_back(p_neighbor_elem);
rHRomComputingModelPart.AddElement(p_neighbor_elem);

// Add the nodes of the neighboring element to the model part
const auto& neighbor_r_geom = p_neighbor_elem->GetGeometry();
const SizeType neighbor_n_nodes = neighbor_r_geom.PointsNumber();
for (IndexType i_neighbor_node = 0; i_neighbor_node < neighbor_n_nodes; ++i_neighbor_node) {
NodeType::Pointer p_neighbor_node = neighbor_r_geom(i_neighbor_node);
hrom_nodes_set.insert(hrom_nodes_set.end(), p_neighbor_node);
rHRomComputingModelPart.AddNode(p_neighbor_node);
}
}
}

// Get the neighbor conditions from each node and add them to the model part
for (auto& neighbor_cond : p_node->GetValue(NEIGHBOUR_CONDITIONS)) {
Kratos::Condition::Pointer p_neighbor_cond = &neighbor_cond;
// Be careful to not add a condition that is already in the model part.
// For this, we will check if the condition is already in our vector of conditions.
if(std::find(hrom_conds_vect.begin(), hrom_conds_vect.end(), p_neighbor_cond) == hrom_conds_vect.end()) {
hrom_conds_vect.push_back(p_neighbor_cond);
rHRomComputingModelPart.AddCondition(p_neighbor_cond);

// Add the nodes of the neighboring condition to the model part
const auto& neighbor_r_geom = p_neighbor_cond->GetGeometry();
const SizeType neighbor_n_nodes = neighbor_r_geom.PointsNumber();
for (IndexType i_neighbor_node = 0; i_neighbor_node < neighbor_n_nodes; ++i_neighbor_node) {
NodeType::Pointer p_neighbor_node = neighbor_r_geom(i_neighbor_node);
hrom_nodes_set.insert(hrom_nodes_set.end(), p_neighbor_node);
rHRomComputingModelPart.AddNode(p_neighbor_node);
}
}
}
}
}
hrom_elems_vect.shrink_to_fit();
hrom_conds_vect.shrink_to_fit();

//TODO: ADD MPC'S

// Add properties to the HROM mesh
// Note that we add all the properties although some of them might note be used in the HROM mesh
auto& r_root_model_part = const_cast<ModelPart&>(rOriginModelPart).GetRootModelPart();
auto& r_properties = r_root_model_part.rProperties();
for (auto it_p_prop = r_properties.ptr_begin(); it_p_prop < r_properties.ptr_end(); ++it_p_prop) {
rHRomComputingModelPart.AddProperties(*it_p_prop);
}

// Create and fill the HROM calculation sub model parts
for (auto& r_orig_sub_mp : rOriginModelPart.SubModelParts()) {
RecursiveHRomModelPartCreation(hrom_nodes_set, hrom_elems_vect, hrom_conds_vect, r_orig_sub_mp, rHRomComputingModelPart);
}
}

//TODO: Make it thin walled and beam compatible
void RomAuxiliaryUtilities::SetHRomVolumetricVisualizationModelPart(
const ModelPart& rOriginModelPart,
Expand Down Expand Up @@ -592,4 +756,16 @@ void RomAuxiliaryUtilities::GetPsiElemental(
}
}

void RomAuxiliaryUtilities::GetJPhiElemental(
Matrix &rJPhiElemental,
const Element::DofsVectorType& rDofs,
const Matrix &rJPhi)
{
for(std::size_t i = 0; i < rDofs.size(); ++i)
{
const Dof<double>& r_dof = *rDofs[i];
noalias(row(rJPhiElemental, i)) = row(rJPhi, r_dof.EquationId());
}
}

} // namespace Kratos
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,24 @@ class KRATOS_API(ROM_APPLICATION) RomAuxiliaryUtilities
const ModelPart& rOriginModelPart,
ModelPart& rHRomComputingModelPart);

/**
* @brief Sets the HROM model part including neighboring entities based on the nodal weights
*
* Provided an origin model part and a parameters object containing the HROM weights,
* this method stores not only the elements and conditions required by the HROM in the destination
* model part, but also includes neighboring elements and conditions of the nodes involved.
* The resulting model part features the same submodelpart hierarchy that the origin has, but is
* augmented with the neighboring elements and conditions.
*
* @param HRomWeights Parameters object containing the HROM elemental and condition weights
* @param rOriginModelPart Origin model part (this is likely the computing model part)
* @param rHRomComputingModelPart Destination model part to store the HROM mesh augmented with neighbours
*/
static void SetHRomComputingModelPartWithNeighbours(
const Parameters HRomWeights,
ModelPart& rOriginModelPart,
ModelPart& rHRomComputingModelPart);

/**
* @brief Sets the HROM skin visualization model part for a volumetric body
* This function detects the skin of the origin modelpart and creates the corresponding skin
Expand Down Expand Up @@ -215,6 +233,21 @@ class KRATOS_API(ROM_APPLICATION) RomAuxiliaryUtilities
const Element::GeometryType& rGeom,
const std::unordered_map<Kratos::VariableData::KeyType, Matrix::size_type>& rVarToRowMapping);

/**
* @brief Obtain the JPhi elemental matrix for a particular element.
* JPhi represents the projection of the Jacobian onto the ROM_BASIS.
* @param rJPhiElemental The matrix to store the result in. Must have the appropriate size already.
* @param rDofs The set of degrees of freedom (DoFs) of the element.
* @param rJPhi The JPhi matrix, from which rows are extracted according to the equation ID of each DoF.
*
* This function loops over all the DoFs for the given element. For each DoF, it uses its equation ID to extract a
* corresponding row from the rJPhi matrix, which is then stored in the corresponding row of rJPhiElemental.
*/
static void GetJPhiElemental(
Matrix &rJPhiElemental,
const Element::DofsVectorType& rDofs,
const Matrix &rJPhi);

///@}

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,18 @@ namespace Kratos

~RomResidualsUtility()= default;

/**
* Resizes a Matrix if it's not the right size
*/
template<typename TMatrix>
static void ResizeIfNeeded(TMatrix& rMat, const std::size_t Rows, const std::size_t Cols)

{
if(rMat.size1() != Rows || rMat.size2() != Cols) {
rMat.resize(Rows, Cols, false);
}
};

SADPR marked this conversation as resolved.
Show resolved Hide resolved
Matrix GetProjectedResidualsOntoPhi()
{
// Getting the number of elements and conditions from the model
Expand Down Expand Up @@ -208,6 +220,70 @@ namespace Kratos
return matrix_residuals;
}

Matrix GetProjectedResidualsOntoJPhi(
SADPR marked this conversation as resolved.
Show resolved Hide resolved
Matrix& rJPhi
)
{
const int n_elements = static_cast<int>(mrModelPart.Elements().size());
const int n_conditions = static_cast<int>(mrModelPart.Conditions().size());

const auto& r_current_process_info = mrModelPart.GetProcessInfo();

//contributions to the system
Vector rhs_contribution;

//vector containing the localization in the system of the different terms
Element::EquationIdVectorType equation_id;
Matrix matrix_residuals( (n_elements + n_conditions), mRomDofs);
Matrix phi_j_elemental;

const auto el_begin = mrModelPart.ElementsBegin();
const auto cond_begin = mrModelPart.ConditionsBegin();

//dofs container initialization
Element::DofsVectorType elem_dofs;
Condition::DofsVectorType cond_dofs;
#pragma omp parallel firstprivate(n_elements, n_conditions, rhs_contribution, equation_id, phi_j_elemental, el_begin, cond_begin, elem_dofs, cond_dofs)
{
#pragma omp for
for (int k = 0; k < n_elements; k++){
auto r_element = el_begin + k;
if (r_element->IsDefined(ACTIVE) && r_element->IsNot(ACTIVE)) continue;

mpScheme->CalculateRHSContribution(*r_element, rhs_contribution, equation_id, r_current_process_info);
r_element->GetDofList(elem_dofs, r_current_process_info);

const std::size_t ndofs = elem_dofs.size();
ResizeIfNeeded(phi_j_elemental, ndofs, mRomDofs);
RomAuxiliaryUtilities::GetJPhiElemental(phi_j_elemental, elem_dofs, rJPhi);

#pragma omp critical
{
noalias(row(matrix_residuals, k)) = prod(trans(phi_j_elemental), rhs_contribution);
}
}

#pragma omp for
for (int k = 0; k < n_conditions; k++){
auto r_condition = cond_begin + k;
if (r_condition->IsDefined(ACTIVE) && r_condition->IsNot(ACTIVE)) continue;

mpScheme->CalculateRHSContribution(*r_condition, rhs_contribution, equation_id, r_current_process_info);
r_condition->GetDofList(cond_dofs, r_current_process_info);

const std::size_t ndofs = cond_dofs.size();
ResizeIfNeeded(phi_j_elemental, ndofs, mRomDofs);
RomAuxiliaryUtilities::GetJPhiElemental(phi_j_elemental, cond_dofs, rJPhi);

#pragma omp critical
{
noalias(row(matrix_residuals, n_elements + k)) = prod(trans(phi_j_elemental), rhs_contribution);
}
}
}
return matrix_residuals;
}

protected:
std::vector< std::string > mNodalVariablesNames;
int mNodalDofs;
Expand Down
Loading