From 1fb103d45986c9c5e5cb0b7579bbfdedd7f73045 Mon Sep 17 00:00:00 2001 From: LABOURASSE Emmanuel <labourassee@gmail.com> Date: Tue, 6 Oct 2020 11:24:46 +0200 Subject: [PATCH] Correction of the Neumann boundary conditions for heat --- .../algorithms/HeatDiamondAlgorithm.cpp | 449 ++++++------------ 1 file changed, 156 insertions(+), 293 deletions(-) diff --git a/src/language/algorithms/HeatDiamondAlgorithm.cpp b/src/language/algorithms/HeatDiamondAlgorithm.cpp index c729f97b2..33d6783e5 100644 --- a/src/language/algorithms/HeatDiamondAlgorithm.cpp +++ b/src/language/algorithms/HeatDiamondAlgorithm.cpp @@ -52,85 +52,40 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( std::cout << "number of bc descr = " << bc_descriptor_list.size() << '\n'; std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh); - NodeValue<bool> is_dirichlet{mesh->connectivity()}; - is_dirichlet.fill(false); - NodeValue<double> dirichlet_value{mesh->connectivity()}; - dirichlet_value.fill(std::numeric_limits<double>::signaling_NaN()); - for (const auto& bc_descriptor : bc_descriptor_list) { bool is_valid_boundary_condition = true; switch (bc_descriptor->type()) { case IBoundaryConditionDescriptor::Type::symmetry: { - // const SymmetryBoundaryConditionDescriptor& sym_bc_descriptor = - // dynamic_cast<const SymmetryBoundaryConditionDescriptor&>(*bc_descriptor); throw NotImplementedError("NIY"); break; } case IBoundaryConditionDescriptor::Type::dirichlet: { const DirichletBoundaryConditionDescriptor& dirichlet_bc_descriptor = dynamic_cast<const DirichletBoundaryConditionDescriptor&>(*bc_descriptor); - - for (size_t i_ref_face_list = 0; i_ref_face_list < mesh->connectivity().template numberOfRefItemList<FaceType>(); - ++i_ref_face_list) { - const auto& ref_face_list = mesh->connectivity().template refItemList<FaceType>(i_ref_face_list); - const RefId& ref = ref_face_list.refId(); - if (ref == dirichlet_bc_descriptor.boundaryDescriptor()) { - MeshNodeBoundary<Dimension> mesh_node_boundary{mesh, ref_face_list}; - - const FunctionSymbolId g_id = dirichlet_bc_descriptor.rhsSymbolId(); - - const auto& node_list = mesh_node_boundary.nodeList(); - - Array<const double> value_list = - InterpolateItemValue<double(TinyVector<Dimension>)>::template interpolate<ItemType::node>(g_id, mesh->xr(), - node_list); - - for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - NodeId node_id = node_list[i_node]; - if (not is_dirichlet[node_id]) { - is_dirichlet[node_id] = true; - dirichlet_value[node_id] = value_list[i_node]; - } - } - - boundary_condition_list.push_back(DirichletBoundaryCondition{node_list, value_list}); - } - } - if constexpr (Dimension > 1) { - for (size_t i_ref_node_list = 0; - i_ref_node_list < mesh->connectivity().template numberOfRefItemList<ItemType::node>(); ++i_ref_node_list) { - const auto& ref_node_list = mesh->connectivity().template refItemList<ItemType::node>(i_ref_node_list); - const RefId& ref = ref_node_list.refId(); + for (size_t i_ref_face_list = 0; + i_ref_face_list < mesh->connectivity().template numberOfRefItemList<FaceType>(); ++i_ref_face_list) { + const auto& ref_face_list = mesh->connectivity().template refItemList<FaceType>(i_ref_face_list); + const RefId& ref = ref_face_list.refId(); if (ref == dirichlet_bc_descriptor.boundaryDescriptor()) { - const FunctionSymbolId g_id = dirichlet_bc_descriptor.rhsSymbolId(); + MeshNodeBoundary<Dimension> mesh_node_boundary{mesh, ref_face_list}; - const auto& node_list = ref_node_list.list(); + const FunctionSymbolId g_id = dirichlet_bc_descriptor.rhsSymbolId(); + MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*mesh); + Array<const FaceId> face_list = ref_face_list.list(); Array<const double> value_list = - InterpolateItemValue<double(TinyVector<Dimension>)>::template interpolate<ItemType::node>(g_id, - mesh->xr(), - node_list); - - for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - NodeId node_id = node_list[i_node]; - if (not is_dirichlet[node_id]) { - is_dirichlet[node_id] = true; - dirichlet_value[node_id] = value_list[i_node]; - } - } - - boundary_condition_list.push_back(DirichletBoundaryCondition{node_list, value_list}); + InterpolateItemValue<double(TinyVector<Dimension>)>::template interpolate<ItemType::face>(g_id, + mesh_data.xl(), + face_list); + boundary_condition_list.push_back(DirichletBoundaryCondition{face_list, value_list}); } } } - break; } case IBoundaryConditionDescriptor::Type::fourier: { - // const FourierBoundaryConditionDescriptor& fourier_bc_descriptor = - // dynamic_cast<const FourierBoundaryConditionDescriptor&>(*bc_descriptor); throw NotImplementedError("NIY"); break; } @@ -154,8 +109,6 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( mesh_data.xl(), face_list); boundary_condition_list.push_back(NeumannBoundaryCondition{face_list, value_list}); - } else { - throw NotImplementedError("Neumann conditions are not supported in 1d"); } } } @@ -190,7 +143,8 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( using T = std::decay_t<decltype(bc)>; if constexpr ((std::is_same_v<T, NeumannBoundaryCondition>) or (std::is_same_v<T, FourierBoundaryCondition>) or - (std::is_same_v<T, SymmetryBoundaryCondition>)) { + (std::is_same_v<T, SymmetryBoundaryCondition>) or + (std::is_same_v<T, DirichletBoundaryCondition>)) { const auto& face_list = bc.faceList(); for (size_t i_face = 0; i_face < face_list.size(); ++i_face) { @@ -211,6 +165,30 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( return compute_face_dof_number; }(); + const FaceValue<const bool> primal_face_is_neumann = [&] { + FaceValue<bool> face_is_neumann{mesh->connectivity()}; + face_is_neumann.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, NeumannBoundaryCondition>) or + (std::is_same_v<T, FourierBoundaryCondition>) or + (std::is_same_v<T, SymmetryBoundaryCondition>)) { + const auto& face_list = bc.faceList(); + + for (size_t i_face = 0; i_face < face_list.size(); ++i_face) { + const FaceId face_id = face_list[i_face]; + face_is_neumann[face_id] = true; + } + } + }, + boundary_condition); + } + + return face_is_neumann; + }(); + const auto& primal_face_to_node_matrix = mesh->connectivity().faceToNodeMatrix(); const auto& face_to_cell_matrix = mesh->connectivity().faceToCellMatrix(); NodeValue<bool> primal_node_is_on_boundary(mesh->connectivity()); @@ -240,27 +218,22 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( } } - FaceValue<bool> primal_face_is_neumann(mesh->connectivity()); + FaceValue<bool> primal_face_is_dirichlet(mesh->connectivity()); if (parallel::size() > 1) { throw NotImplementedError("Calculation of face_is_neumann is incorrect"); } - primal_face_is_neumann.fill(false); + primal_face_is_dirichlet.fill(false); for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { - if (primal_face_is_on_boundary[face_id]) { - 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 is_dirichlet[node_id]) { - primal_face_is_neumann[face_id] = true; - } - } - } + primal_face_is_dirichlet[face_id] = (primal_face_is_on_boundary[face_id] && (!primal_face_is_neumann[face_id])); } + MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*mesh); CellValue<double> Tj = InterpolateItemValue<double(TinyVector<Dimension>)>::template interpolate<ItemType::cell>(T_id, mesh_data.xj()); - + FaceValue<double> Tl = + InterpolateItemValue<double(TinyVector<Dimension>)>::template interpolate<ItemType::face>(T_id, mesh_data.xl()); NodeValue<double> Tr(mesh->connectivity()); const NodeValue<const TinyVector<Dimension>>& xr = mesh->xr(); @@ -352,6 +325,7 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( FaceId face_id = node_to_face_matrix[i_node][i_face]; if (primal_face_is_on_boundary[face_id]) { w_rl(i_node, i_face) = x[cpt_face++]; + Tr[i_node] += w_rl(i_node, i_face) * Tl[face_id]; } } } @@ -441,32 +415,21 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( SparseMatrixDescriptor S{number_of_dof}; for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { - if (not primal_face_is_neumann[face_id]) { - const auto& primal_face_to_cell = face_to_cell_matrix[face_id]; - const double beta_l = 1. / Dimension * alpha_l[face_id] * mes_l[face_id]; - - for (size_t i_cell = 0; i_cell < primal_face_to_cell.size(); ++i_cell) { - const CellId cell_id1 = primal_face_to_cell[i_cell]; - for (size_t j_cell = 0; j_cell < primal_face_to_cell.size(); ++j_cell) { - const CellId cell_id2 = primal_face_to_cell[j_cell]; - if (i_cell == j_cell) { - S(cell_dof_number[cell_id1], cell_dof_number[cell_id2]) += beta_l; - } else { - S(cell_dof_number[cell_id1], cell_dof_number[cell_id2]) -= beta_l; + const auto& primal_face_to_cell = face_to_cell_matrix[face_id]; + const double beta_l = 1. / Dimension * alpha_l[face_id] * mes_l[face_id]; + for (size_t i_cell = 0; i_cell < primal_face_to_cell.size(); ++i_cell) { + const CellId cell_id1 = primal_face_to_cell[i_cell]; + for (size_t j_cell = 0; j_cell < primal_face_to_cell.size(); ++j_cell) { + const CellId cell_id2 = primal_face_to_cell[j_cell]; + if (i_cell == j_cell) { + S(cell_dof_number[cell_id1], cell_dof_number[cell_id2]) += beta_l; + if (primal_face_is_neumann[face_id]) { + S(face_dof_number[face_id], cell_dof_number[cell_id2]) -= beta_l; } + } else { + S(cell_dof_number[cell_id1], cell_dof_number[cell_id2]) -= beta_l; } } - } else { - const auto& primal_face_to_cell = face_to_cell_matrix[face_id]; - const double beta_l = 1. / Dimension * alpha_l[face_id] * mes_l[face_id]; - Assert(primal_face_to_cell.size() == 1, "Wrong number of cells for a boundary face"); - for (size_t i_cell = 0; i_cell < primal_face_to_cell.size(); ++i_cell) { - const CellId cell_id1 = primal_face_to_cell[i_cell]; - S(cell_dof_number[cell_id1], cell_dof_number[cell_id1]) += beta_l; - S(cell_dof_number[cell_id1], face_dof_number[face_id]) -= beta_l; - S(face_dof_number[face_id], face_dof_number[face_id]) += beta_l; - S(face_dof_number[face_id], cell_dof_number[cell_id1]) -= beta_l; - } } } @@ -505,48 +468,48 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( const auto& primal_face_cell_is_reversed = mesh->connectivity().cellFaceIsReversed(); const auto& face_local_numbers_in_their_cells = mesh->connectivity().faceLocalNumbersInTheirCells(); const auto& primal_node_to_cell_matrix = mesh->connectivity().nodeToCellMatrix(); - for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { - if (face_to_cell_matrix[face_id].size() > 1) { - const double alpha_face_id = alpha_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 is_dirichlet[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); - } - }(); + const double alpha_face_id = alpha_l[face_id]; - CellId dual_cell_id = face_dual_cell_id[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_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); + 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]; - const double a_ir = alpha_face_id * (nil, Clr); + 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); + } + }(); - 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]; - S(cell_dof_number[i_id], cell_dof_number[j_id]) -= w_rj(node_id, j_cell) * a_ir; - } - if (primal_node_is_on_boundary[node_id]) { - for (size_t l_face = 0; l_face < node_to_face_matrix[node_id].size(); ++l_face) { - FaceId l_id = node_to_face_matrix[node_id][l_face]; - if (primal_face_is_neumann[l_id]) { - S(cell_dof_number[i_id], face_dof_number[l_id]) -= w_rl(node_id, l_face) * a_ir; - } + 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); + + const double a_ir = alpha_face_id * (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]; + S(cell_dof_number[i_id], cell_dof_number[j_id]) -= w_rj(node_id, j_cell) * a_ir; + if (primal_face_is_neumann[face_id]) { + S(face_dof_number[face_id], cell_dof_number[j_id]) += w_rj(node_id, j_cell) * a_ir; + } + } + if (primal_node_is_on_boundary[node_id]) { + for (size_t l_face = 0; l_face < node_to_face_matrix[node_id].size(); ++l_face) { + FaceId l_id = node_to_face_matrix[node_id][l_face]; + if (primal_face_is_on_boundary[l_id]) { + S(cell_dof_number[i_id], face_dof_number[l_id]) -= w_rl(node_id, l_face) * a_ir; + if (primal_face_is_neumann[face_id]) { + S(face_dof_number[face_id], face_dof_number[l_id]) += w_rl(node_id, l_face) * a_ir; } } } @@ -556,125 +519,41 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( } } } - // Termes pour Neumann et Fourier for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { - if (primal_face_is_neumann[face_id]) { - int nb_node_per_face = primal_face_to_node_matrix[face_id].size(); - 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 is_dirichlet[node_id]) { - 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]; - S(face_dof_number[face_id], cell_dof_number[j_id]) -= (1. / nb_node_per_face) * w_rj(node_id, j_cell); - } - } - } - } - } - - for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { - if (primal_face_is_neumann[face_id]) { + if (primal_face_is_dirichlet[face_id]) { S(face_dof_number[face_id], face_dof_number[face_id]) += 1; } - if (primal_face_is_neumann[face_id]) { - int nb_node_per_face = primal_face_to_node_matrix[face_id].size(); - 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 is_dirichlet[node_id]) { - for (size_t l_face = 0; l_face < node_to_face_matrix[node_id].size(); ++l_face) { - FaceId face_id2 = node_to_face_matrix[node_id][l_face]; - if (primal_face_is_neumann[face_id2]) { - S(face_dof_number[face_id], face_dof_number[face_id2]) -= - (1. / nb_node_per_face) * w_rl(node_id, l_face); - } - } - } - } - } } CellValue<double> fj = InterpolateItemValue<double(TinyVector<Dimension>)>::template interpolate<ItemType::cell>(f_id, mesh_data.xj()); const CellValue<const double> primal_Vj = mesh_data.Vj(); - CRSMatrix A{S}; Vector<double> b{number_of_dof}; - const auto& primal_cell_to_face_matrix = mesh->connectivity().cellToFaceMatrix(); for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { b[cell_dof_number[cell_id]] = fj[cell_id] * primal_Vj[cell_id]; } - - { // Dirichlet - NodeValue<bool> node_tag{mesh->connectivity()}; - node_tag.fill(false); + // Dirichlet on b^L_D + { 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& face_list = bc.faceList(); 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); - b[cell_dof_number[cell_id]] += alpha_l[face_id] * value_list[i_node] * (nil, Clr); - } - } - } - } - } - } - } + for (size_t i_face = 0; i_face < face_list.size(); ++i_face) { + const FaceId face_id = face_list[i_face]; + b[face_dof_number[face_id]] += value_list[i_face]; // sign } } }, boundary_condition); } } - + // EL b^L for (const auto& boundary_condition : boundary_condition_list) { std::visit( [&](auto&& bc) { @@ -685,93 +564,77 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( const auto& value_list = bc.valueList(); for (size_t i_face = 0; i_face < face_list.size(); ++i_face) { FaceId face_id = face_list[i_face]; - CellId cell_id = face_to_cell_matrix[face_id][0]; Assert(face_to_cell_matrix[face_id].size() == 1); - b[cell_dof_number[cell_id]] += mes_l[face_id] * value_list[i_face]; - } - } - }, - boundary_condition); - } - 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) { - NodeId node_id = node_list[i_node]; - for (size_t i_face = 0; i_face < node_to_face_matrix[node_id].size(); ++i_face) { - FaceId face_id = node_to_face_matrix[node_id][i_face]; - if (primal_face_is_neumann[face_id]) { - int nb_node_per_face = primal_face_to_node_matrix[face_id].size(); - b[face_dof_number[face_id]] += (1. / nb_node_per_face) * value_list[i_node]; - } - } + b[face_dof_number[face_id]] += mes_l[face_id] * value_list[i_face]; // sign } } }, boundary_condition); } - for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { - if (primal_face_is_neumann[face_id]) { - CellId cell_id = face_to_cell_matrix[face_id][0]; - const bool is_face_reversed_for_cell_i = - primal_face_cell_is_reversed(cell_id, face_local_numbers_in_their_cells(face_id, 0)); - 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 (is_dirichlet[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); - b[cell_dof_number[cell_id]] -= alpha_l[face_id] * (nil, Clr) * dirichlet_value[node_id]; /// - } - } - } - } - } - } - Vector<double> T{number_of_dof}; T = 0; - - BiCGStab{b, A, T, 1000, 1e-15}; - - Vector r = A * T - b; - - std::cout << "real residu = " << std::sqrt((r, r)) << '\n'; + { + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { T[cell_dof_number[cell_id]] = Tj[cell_id]; }); + parallel_for( + mesh->numberOfFaces(), PUGS_LAMBDA(FaceId face_id) { + if (primal_face_is_on_boundary[face_id]) { + T[face_dof_number[face_id]] = Tl[face_id]; + } + }); + T = 1; + } + BiCGStab{b, A, T, 1000, 1e-9}; CellValue<double> Temperature{mesh->connectivity()}; - + FaceValue<double> Temperature_face{mesh->connectivity()}; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { Temperature[cell_id] = T[cell_dof_number[cell_id]]; }); - + parallel_for( + mesh->numberOfFaces(), PUGS_LAMBDA(FaceId face_id) { + if (primal_face_is_neumann[face_id]) { + Temperature_face[face_id] = T[face_dof_number[face_id]]; + } else { + Temperature_face[face_id] = Tl[face_id]; + } + }); Vector<double> error{mesh->numberOfCells()}; + CellValue<double> cell_error{mesh->connectivity()}; + Vector<double> face_error{mesh->numberOfFaces()}; + double error_max = 0.; + size_t cell_max = 0; parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - error[cell_id] = (Temperature[cell_id] - Tj[cell_id]) * sqrt(primal_Vj[cell_id]); + error[cell_id] = (Temperature[cell_id] - Tj[cell_id]) * sqrt(primal_Vj[cell_id]); + cell_error[cell_id] = (Temperature[cell_id] - Tj[cell_id]); + }); + parallel_for( + mesh->numberOfFaces(), PUGS_LAMBDA(FaceId face_id) { + if (primal_face_is_on_boundary[face_id]) { + face_error[face_id] = (Temperature_face[face_id] - Tl[face_id]) * sqrt(mes_l[face_id]); + } else { + face_error[face_id] = 0; + } }); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); cell_id++) { + if (error_max < std::abs(cell_error[cell_id])) { + error_max = std::abs(cell_error[cell_id]); + cell_max = cell_id; + } + } - std::cout << "||Error||_2 = " << std::sqrt((error, error)) << "\n"; + std::cout << " ||Error||_max (cell)= " << error_max << " on cell " << cell_max << "\n"; + std::cout << "||Error||_2 (cell)= " << std::sqrt((error, error)) << "\n"; + std::cout << "||Error||_2 (face)= " << std::sqrt((face_error, face_error)) << "\n"; + std::cout << "||Error||_2 (total)= " << std::sqrt((error, error)) + std::sqrt((face_error, face_error)) << "\n"; { VTKWriter vtk_writer("Temperature_" + std::to_string(Dimension), 0.01); vtk_writer.write(mesh, {NamedItemValue{"T", Temperature}, NamedItemValue{"Vj", primal_Vj}, - NamedItemValue{"Texact", Tj}}, + NamedItemValue{"Texact", Tj}, NamedItemValue{"error", cell_error}}, 0, true); // forces last output } @@ -786,13 +649,13 @@ class HeatDiamondScheme<Dimension>::DirichletBoundaryCondition { private: const Array<const double> m_value_list; - const Array<const NodeId> m_node_list; + const Array<const FaceId> m_face_list; public: - const Array<const NodeId>& - nodeList() const + const Array<const FaceId>& + faceList() const { - return m_node_list; + return m_face_list; } const Array<const double>& @@ -801,10 +664,10 @@ class HeatDiamondScheme<Dimension>::DirichletBoundaryCondition return m_value_list; } - DirichletBoundaryCondition(const Array<const NodeId>& node_list, const Array<const double>& value_list) - : m_value_list{value_list}, m_node_list{node_list} + DirichletBoundaryCondition(const Array<const FaceId>& face_list, const Array<const double>& value_list) + : m_value_list{value_list}, m_face_list{face_list} { - Assert(m_value_list.size() == m_node_list.size()); + Assert(m_value_list.size() == m_face_list.size()); } ~DirichletBoundaryCondition() = default; -- GitLab