From 4f5b355eee3c5575cb439abf01351820ca5bbef2 Mon Sep 17 00:00:00 2001 From: Julie PATELA <julie.patela.ocre@cea.fr> Date: Thu, 20 Aug 2020 09:23:36 +0200 Subject: [PATCH] Add internal's node matrix and Dirichlet's boundary condition --- .../algorithms/ElasticityDiamondAlgorithm.cpp | 259 +++++++++++++++--- .../algorithms/ElasticityDiamondAlgorithm.hpp | 3 +- src/language/modules/SchemeModule.cpp | 11 +- 3 files changed, 227 insertions(+), 46 deletions(-) diff --git a/src/language/algorithms/ElasticityDiamondAlgorithm.cpp b/src/language/algorithms/ElasticityDiamondAlgorithm.cpp index f51e7678e..e7e8de72e 100644 --- a/src/language/algorithms/ElasticityDiamondAlgorithm.cpp +++ b/src/language/algorithms/ElasticityDiamondAlgorithm.cpp @@ -27,7 +27,8 @@ ElasticityDiamondScheme<Dimension>::ElasticityDiamondScheme( const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list, const FunctionSymbolId& lambda_id, const FunctionSymbolId& mu_id, - const FunctionSymbolId& f_id) + const FunctionSymbolId& f_id, + const FunctionSymbolId& U_id) { using ConnectivityType = Connectivity<Dimension>; using MeshType = Mesh<ConnectivityType>; @@ -359,6 +360,9 @@ ElasticityDiamondScheme<Dimension>::ElasticityDiamondScheme( diamond_mesh_data .xj()); + CellValue<TinyVector<Dimension>> Uj = InterpolateItemValue<TinyVector<Dimension>( + TinyVector<Dimension>)>::template interpolate<ItemType::cell>(U_id, mesh_data.xj()); + CellValue<TinyVector<Dimension>> fj = InterpolateItemValue<TinyVector<Dimension>( TinyVector<Dimension>)>::template interpolate<ItemType::cell>(f_id, mesh_data.xj()); @@ -427,6 +431,22 @@ ElasticityDiamondScheme<Dimension>::ElasticityDiamondScheme( return computed_face_dual_cell_id; }(); + NodeValue<const NodeId> dual_node_primal_node_id = [=]() { + CellValue<NodeId> cell_ignored_id{mesh->connectivity()}; + cell_ignored_id.fill(NodeId{std::numeric_limits<unsigned int>::max()}); + + NodeValue<NodeId> node_primal_id{mesh->connectivity()}; + + parallel_for( + mesh->numberOfNodes(), PUGS_LAMBDA(NodeId node_id) { node_primal_id[node_id] = node_id; }); + + NodeValue<NodeId> computed_dual_node_primal_node_id{diamond_mesh->connectivity()}; + + mapper->toDualNode(node_primal_id, cell_ignored_id, computed_dual_node_primal_node_id); + + return computed_dual_node_primal_node_id; + }(); + TinyMatrix<Dimension, double> eye = zero; for (size_t i = 0; i < Dimension; ++i) { eye(i, i) = 1; @@ -437,35 +457,84 @@ ElasticityDiamondScheme<Dimension>::ElasticityDiamondScheme( const auto& face_local_numbers_in_their_cells = mesh->connectivity().faceLocalNumbersInTheirCells(); SparseMatrixDescriptor S{number_of_dof * Dimension}; for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { - if (not primal_face_is_on_boundary[face_id]) { - const double beta_mu_l = (1. / Dimension) * alpha_mu_l[face_id] * mes_l[face_id]; - const double beta_lambda_l = (1. / Dimension) * alpha_lambda_l[face_id] * mes_l[face_id]; - const auto& primal_face_to_cell = face_to_cell_matrix[face_id]; - for (size_t i_cell = 0; i_cell < primal_face_to_cell.size(); ++i_cell) { - const CellId i_id = primal_face_to_cell[i_cell]; - const bool is_face_reversed_for_cell_i = - primal_face_cell_is_reversed(i_id, face_local_numbers_in_their_cells(face_id, i_cell)); - const TinyVector<Dimension> nil = [&] { - if (is_face_reversed_for_cell_i) { - return -primal_nlr(face_id, 0); - } else { - return primal_nlr(face_id, 0); + const double beta_mu_l = (1. / Dimension) * alpha_mu_l[face_id] * mes_l[face_id]; + const double beta_lambda_l = (1. / Dimension) * alpha_lambda_l[face_id] * mes_l[face_id]; + const auto& primal_face_to_cell = face_to_cell_matrix[face_id]; + for (size_t i_cell = 0; i_cell < primal_face_to_cell.size(); ++i_cell) { + const CellId i_id = primal_face_to_cell[i_cell]; + const bool is_face_reversed_for_cell_i = + primal_face_cell_is_reversed(i_id, face_local_numbers_in_their_cells(face_id, i_cell)); + const TinyVector<Dimension> nil = [&] { + if (is_face_reversed_for_cell_i) { + return -primal_nlr(face_id, 0); + } else { + return primal_nlr(face_id, 0); + } + }(); + for (size_t j_cell = 0; j_cell < primal_face_to_cell.size(); ++j_cell) { + const CellId j_id = primal_face_to_cell[j_cell]; + TinyMatrix<Dimension, double> M = + beta_mu_l * eye + beta_mu_l * tensorProduct(nil, nil) + beta_lambda_l * tensorProduct(nil, nil); + if (i_cell == j_cell) { + for (size_t i = 0; i < Dimension; ++i) { + for (size_t j = 0; j < Dimension; ++j) { + S((cell_dof_number[i_id] * Dimension) + i, (cell_dof_number[j_id] * Dimension) + j) += M(i, j); + } } - }(); - for (size_t j_cell = 0; j_cell < primal_face_to_cell.size(); ++j_cell) { - const CellId j_id = primal_face_to_cell[j_cell]; - TinyMatrix<Dimension, double> M = - beta_mu_l * eye + beta_mu_l * tensorProduct(nil, nil) + beta_lambda_l * tensorProduct(nil, nil); - if (i_cell == j_cell) { - for (size_t i = 0; i < Dimension; ++i) { - for (size_t j = 0; j < Dimension; ++j) { - S((cell_dof_number[i_id] * Dimension) + i, (cell_dof_number[j_id] * Dimension) + j) += M(i, j); - } + } else { + for (size_t i = 0; i < Dimension; ++i) { + for (size_t j = 0; j < Dimension; ++j) { + S((cell_dof_number[i_id] * Dimension) + i, (cell_dof_number[j_id] * Dimension) + j) -= M(i, j); } - } else { - for (size_t i = 0; i < Dimension; ++i) { - for (size_t j = 0; j < Dimension; ++j) { - S((cell_dof_number[i_id] * Dimension) + i, (cell_dof_number[j_id] * Dimension) + j) -= M(i, j); + } + } + } + } + } + + const auto& dual_Cjr = diamond_mesh_data.Cjr(); + const auto& dual_cell_to_node_matrix = diamond_mesh->connectivity().cellToNodeMatrix(); + const auto& primal_node_to_cell_matrix = mesh->connectivity().nodeToCellMatrix(); + for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { + const double alpha_mu_face_id = alpha_mu_l[face_id]; + const double alpha_lambda_face_id = alpha_lambda_l[face_id]; + + for (size_t i_face_cell = 0; i_face_cell < face_to_cell_matrix[face_id].size(); ++i_face_cell) { + CellId i_id = face_to_cell_matrix[face_id][i_face_cell]; + const bool is_face_reversed_for_cell_i = + primal_face_cell_is_reversed(i_id, face_local_numbers_in_their_cells(face_id, i_face_cell)); + + for (size_t i_node = 0; i_node < primal_face_to_node_matrix[face_id].size(); ++i_node) { + NodeId node_id = primal_face_to_node_matrix[face_id][i_node]; + + if (not primal_node_is_on_boundary[node_id]) { + const TinyVector<Dimension> nil = [&] { + if (is_face_reversed_for_cell_i) { + return -primal_nlr(face_id, i_node); + } else { + return primal_nlr(face_id, i_node); + } + }(); + + CellId dual_cell_id = face_dual_cell_id[face_id]; + + for (size_t i_dual_node = 0; i_dual_node < dual_cell_to_node_matrix[dual_cell_id].size(); ++i_dual_node) { + const NodeId dual_node_id = dual_cell_to_node_matrix[dual_cell_id][i_dual_node]; + if (dual_node_primal_node_id[dual_node_id] == node_id) { + const TinyVector<Dimension> Clr = dual_Cjr(dual_cell_id, i_dual_node); + + TinyMatrix<Dimension, double> M = alpha_mu_face_id * (Clr, nil) * eye + + alpha_mu_face_id * tensorProduct(Clr, nil) + + alpha_lambda_face_id * tensorProduct(nil, Clr); + + for (size_t j_cell = 0; j_cell < primal_node_to_cell_matrix[node_id].size(); ++j_cell) { + CellId j_id = primal_node_to_cell_matrix[node_id][j_cell]; + for (size_t i = 0; i < Dimension; ++i) { + for (size_t j = 0; j < Dimension; ++j) { + S((cell_dof_number[i_id] * Dimension) + i, (cell_dof_number[j_id] * Dimension) + j) -= + w_rj(node_id, j_cell) * M(i, j); + } + } } } } @@ -473,13 +542,7 @@ ElasticityDiamondScheme<Dimension>::ElasticityDiamondScheme( } } } - // for (size_t i = 0; i < S.numberOfRows(); ++i) { - // for (size_t j = 0; j < S.numberOfRows(); ++j) { - // std::cout << S(i, j) << " ; "; - // } - // std::cout << "\n"; - // } - // std::exit(0); + CRSMatrix A{S}; Vector<double> b{number_of_dof * Dimension}; for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { @@ -488,6 +551,80 @@ ElasticityDiamondScheme<Dimension>::ElasticityDiamondScheme( } } + const auto& primal_cell_to_face_matrix = mesh->connectivity().cellToFaceMatrix(); + // Dirichlet + NodeValue<bool> node_tag{mesh->connectivity()}; + node_tag.fill(false); + for (const auto& boundary_condition : boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<T, DirichletBoundaryCondition>) { + const auto& node_list = bc.nodeList(); + const auto& value_list = bc.valueList(); + for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { + const NodeId node_id = node_list[i_node]; + if (not node_tag[node_id]) { + node_tag[node_id] = true; + + const auto& node_cells = primal_node_to_cell_matrix[node_id]; + for (size_t i_cell = 0; i_cell < node_cells.size(); ++i_cell) { + const CellId cell_id = node_cells[i_cell]; + + const auto& primal_cell_to_face = primal_cell_to_face_matrix[cell_id]; + + for (size_t i_cell_face = 0; i_cell_face < primal_cell_to_face.size(); ++i_cell_face) { + FaceId face_id = primal_cell_to_face_matrix[cell_id][i_cell_face]; + + const bool is_face_reversed_for_cell_i = [=] { + for (size_t i_face = 0; i_face < primal_cell_to_face.size(); ++i_face) { + FaceId primal_face_id = primal_cell_to_face[i_face]; + if (primal_face_id == face_id) { + return primal_face_cell_is_reversed(cell_id, i_face); + } + } + Assert(false, "cannot find cell's face"); + return false; + }(); + + const auto& primal_face_to_node = primal_face_to_node_matrix[face_id]; + + for (size_t i_face_node = 0; i_face_node < primal_face_to_node.size(); ++i_face_node) { + if (primal_face_to_node[i_face_node] == node_id) { + const TinyVector<Dimension> nil = [=] { + if (is_face_reversed_for_cell_i) { + return -primal_nlr(face_id, i_face_node); + } else { + return primal_nlr(face_id, i_face_node); + } + }(); + + CellId dual_cell_id = face_dual_cell_id[face_id]; + + for (size_t i_dual_node = 0; i_dual_node < dual_cell_to_node_matrix[dual_cell_id].size(); + ++i_dual_node) { + const NodeId dual_node_id = dual_cell_to_node_matrix[dual_cell_id][i_dual_node]; + if (dual_node_primal_node_id[dual_node_id] == node_id) { + const TinyVector<Dimension> Clr = dual_Cjr(dual_cell_id, i_dual_node); + TinyMatrix<Dimension, double> M = alpha_mu_l[face_id] * (Clr, nil) * eye + + alpha_mu_l[face_id] * tensorProduct(Clr, nil) + + alpha_lambda_l[face_id] * tensorProduct(nil, Clr); + for (size_t i = 0; i < Dimension; ++i) { + b[(cell_dof_number[cell_id] * Dimension) + i] += (M * value_list[i_node])[i]; + } + } + } + } + } + } + } + } + } + } + }, + boundary_condition); + } + Vector<double> U{number_of_dof * Dimension}; U = 0; @@ -495,19 +632,58 @@ ElasticityDiamondScheme<Dimension>::ElasticityDiamondScheme( Vector r = A * U - b; + // for (CellId j = 0; j < number_of_dof; ++j) { + // for (size_t l = 0; l < Dimension; ++l) { + // std::cout << "Ucalc : " << U[(cell_dof_number[j] * Dimension) + l] << "\n"; + // } + // } + std::cout << "real residu = " << std::sqrt((r, r)) << '\n'; - CellValue<double> Speed{mesh->connectivity()}; + CellValue<TinyVector<Dimension>> Speed{mesh->connectivity()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { Speed[cell_id] = U[cell_dof_number[cell_id]]; }); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + for (size_t i = 0; i < Dimension; ++i) { + Speed[cell_id][i] = U[(cell_dof_number[cell_id] * Dimension) + i]; + } + } + Vector<double> Uexacte{number_of_dof * Dimension}; + for (CellId j = 0; j < number_of_dof; ++j) { + for (size_t l = 0; l < Dimension; ++l) { + Uexacte[(cell_dof_number[j] * Dimension) + l] = Uj[j][l]; + } + } + // std::cout << "A*Uex - b =\n"; + // for (CellId i_id = 0; i_id < number_of_dof; ++i_id) { + // for (size_t j = 0; j < Dimension; ++j) { + // std::cout << (A * Uexacte - b)[(cell_dof_number[i_id] * Dimension) + j] << "\n"; + // } + // } + // std::cout << "Vecteur AU - b: \n"; + // for (CellId i = 0; i < number_of_dof; ++i) { + // // double temp = 0; + // for (size_t k = 0; k < Dimension; ++k) { + // double temp = 0; + // for (CellId j = 0; j < number_of_dof; ++j) { + // for (size_t l = 0; l < Dimension; ++l) { + // temp += S((cell_dof_number[i] * Dimension) + k, (cell_dof_number[j] * Dimension) + l) * Uj[j][l]; + // } + // } + // std::cout << temp << "; " << b[(cell_dof_number[i] * Dimension) + k] << "=> " + // << temp - b[(cell_dof_number[i] * Dimension) + k] << "\n"; + // } + // } + + // std::cout << "Vecteur Uexacte : \n"; + // for (CellId i = 0; i < number_of_dof; ++i) { + // std::cout << Uj[i] << "\n"; + // } VTKWriter vtk_writer("Speed_" + std::to_string(Dimension), 0.01); - vtk_writer.write(mesh, {NamedItemValue{"U", Speed}}, 0, + vtk_writer.write(mesh, {NamedItemValue{"U", Speed}, NamedItemValue{"Uexacte", Uj}}, 0, true); // forces last output } - } else { throw NotImplementedError("not done in 1d"); } @@ -596,6 +772,7 @@ template ElasticityDiamondScheme<1>::ElasticityDiamondScheme( const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&, const FunctionSymbolId&, const FunctionSymbolId&, + const FunctionSymbolId&, const FunctionSymbolId&); template ElasticityDiamondScheme<2>::ElasticityDiamondScheme( @@ -603,6 +780,7 @@ template ElasticityDiamondScheme<2>::ElasticityDiamondScheme( const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&, const FunctionSymbolId&, const FunctionSymbolId&, + const FunctionSymbolId&, const FunctionSymbolId&); template ElasticityDiamondScheme<3>::ElasticityDiamondScheme( @@ -610,4 +788,5 @@ template ElasticityDiamondScheme<3>::ElasticityDiamondScheme( const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&, const FunctionSymbolId&, const FunctionSymbolId&, + const FunctionSymbolId&, const FunctionSymbolId&); diff --git a/src/language/algorithms/ElasticityDiamondAlgorithm.hpp b/src/language/algorithms/ElasticityDiamondAlgorithm.hpp index 6eea3945a..733aa7d58 100644 --- a/src/language/algorithms/ElasticityDiamondAlgorithm.hpp +++ b/src/language/algorithms/ElasticityDiamondAlgorithm.hpp @@ -22,7 +22,8 @@ class ElasticityDiamondScheme const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list, const FunctionSymbolId& lambda_id, const FunctionSymbolId& mu_id, - const FunctionSymbolId& f_id); + const FunctionSymbolId& f_id, + const FunctionSymbolId& U_id); }; #endif // ELASTICITY_DIAMOND_ALGORITHM_HPP diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp index 3ac4f789f..61c90914a 100644 --- a/src/language/modules/SchemeModule.cpp +++ b/src/language/modules/SchemeModule.cpp @@ -264,24 +264,25 @@ SchemeModule::SchemeModule() std::make_shared<BuiltinFunctionEmbedder< void(std::shared_ptr<const IMesh>, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&, - const FunctionSymbolId&, const FunctionSymbolId&, const FunctionSymbolId&)>>( + const FunctionSymbolId&, const FunctionSymbolId&, const FunctionSymbolId&, + const FunctionSymbolId&)>>( [](std::shared_ptr<const IMesh> p_mesh, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list, const FunctionSymbolId& lambda_id, const FunctionSymbolId& mu_id, - const FunctionSymbolId& f_id) -> void { + const FunctionSymbolId& f_id, const FunctionSymbolId& U_id) -> void { switch (p_mesh->dimension()) { case 1: { - ElasticityDiamondScheme<1>{p_mesh, bc_descriptor_list, lambda_id, mu_id, f_id}; + ElasticityDiamondScheme<1>{p_mesh, bc_descriptor_list, lambda_id, mu_id, f_id, U_id}; break; } case 2: { - ElasticityDiamondScheme<2>{p_mesh, bc_descriptor_list, lambda_id, mu_id, f_id}; + ElasticityDiamondScheme<2>{p_mesh, bc_descriptor_list, lambda_id, mu_id, f_id, U_id}; break; } case 3: { - ElasticityDiamondScheme<3>{p_mesh, bc_descriptor_list, lambda_id, mu_id, f_id}; + ElasticityDiamondScheme<3>{p_mesh, bc_descriptor_list, lambda_id, mu_id, f_id, U_id}; break; } default: { -- GitLab