diff --git a/src/language/algorithms/HeatDiamondAlgorithm.cpp b/src/language/algorithms/HeatDiamondAlgorithm.cpp index be6552c2761c29f822e30265a6bd2ab7280de579..0a6058e73612670524dc9bfece6e2e5ff04432c8 100644 --- a/src/language/algorithms/HeatDiamondAlgorithm.cpp +++ b/src/language/algorithms/HeatDiamondAlgorithm.cpp @@ -211,6 +211,22 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( } } + FaceValue<bool> primal_face_is_neumann(mesh->connectivity()); + if (parallel::size() > 1) { + throw NotImplementedError("Calculation of face_is_neumann is incorrect"); + } + + primal_face_is_neumann.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; + } + } + } + } MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*mesh); CellValue<double> Tj = @@ -270,7 +286,7 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( } } LocalRectangularMatrix<double> A{Dimension + 1, node_to_cell.size() + nb_face_used}; - for (size_t j = 0; j < node_to_cell.size(); j++) { + for (size_t j = 0; j < node_to_cell.size() + nb_face_used; j++) { A(0, j) = 1; } for (size_t i = 1; i < Dimension + 1; i++) { @@ -302,13 +318,34 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( Tr[i_node] += x[j] * Tj[node_to_cell[j]]; w_rj(i_node, j) = x[j]; } - int cpt_face = 0; + int cpt_face = node_to_cell.size(); for (size_t i_face = 0; i_face < node_to_face_matrix[i_node].size(); ++i_face) { 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++]; } } + std::cout << i_node << ":"; + double s = 0; + for (size_t i = 0; i < x.size(); ++i) { + std::cout << ' ' << x[i]; + s += x[i]; + } + std::cout << " -> " << s << '\n'; + } + } + + for (NodeId i_node = 0; i_node < mesh->numberOfNodes(); ++i_node) { + if (not is_dirichlet[i_node]) { + std::cout << "node = " << i_node << '\n'; + for (size_t i_cell = 0; i_cell < node_to_cell_matrix[i_node].size(); ++i_cell) { + std::cout << "w_rj(" << i_node << ',' << i_cell << ") = " << w_rj(i_node, i_cell) << '\n'; + } + if (primal_node_is_on_boundary[i_node]) { + for (size_t i_face = 0; i_face < node_to_face_matrix[i_node].size(); ++i_face) { + std::cout << "w_rl(" << i_node << ',' << i_face << ") = " << w_rl(i_node, i_face) << '\n'; + } + } } } @@ -393,6 +430,7 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( return computed_alpha_l; }(); + SparseMatrixDescriptor S{number_of_dof}; for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { const auto& primal_face_to_cell = face_to_cell_matrix[face_id]; @@ -478,10 +516,29 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( const double a_ir = alpha_face_id * (nil, Clr); + double sum_w = 0; + 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; + sum_w += w_rj(node_id, j_cell); } + std::cout << node_id << " "; + if (primal_node_is_on_boundary[node_id]) { + std::cout << "face: " << sum_w << " -> "; + 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; + sum_w += w_rl(node_id, l_face); + std::cout << "[added value :" << w_rl(node_id, l_face) * a_ir << "] Clr=" << Clr + << " nil=" << nil << " "; + } + } + } else { + std::cout << "inner: "; + } + std::cout << "sum_w=" << sum_w << '\n'; } } } @@ -489,6 +546,105 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( } } } + // // test + // const auto& cell_to_face_matrix = mesh->connectivity().cellToFaceMatrix(); + // 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>)) { + // const auto& face_list = bc.faceList(); + // // const auto& value_list = bc.valueList(); + // for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + // for (size_t i_face = 0; i_face < face_list.size(); ++i_face) { + // FaceId face_id = face_list[i_face]; + // for (size_t i_face2 = 0; i_face2 < cell_to_face_matrix[cell_id].size(); ++i_face2) { + // FaceId face_id2 = cell_to_face_matrix[cell_id][i_face2]; + // if (not primal_face_is_on_boundary[face_id2]) { + // const double alpha_face_id = alpha_l[face_id2]; + + // const bool is_face_reversed_for_cell_i = primal_face_cell_is_reversed(cell_id, i_face2); + // for (size_t i_node = 0; i_node < primal_face_to_node_matrix[face_id2].size(); ++i_node) { + // NodeId node_id = primal_face_to_node_matrix[face_id2][i_node]; + // const TinyVector<Dimension> nil = [&] { + // if (is_face_reversed_for_cell_i) { + // return -primal_nlr(face_id2, i_node); + // } else { + // return primal_nlr(face_id2, i_node); + // } + // }(); + // if (not is_dirichlet[node_id]) { + // if (primal_node_is_on_boundary[node_id]) { + // CellId dual_cell_id = face_dual_cell_id[face_id2]; + + // 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 l_face = 0; l_face < node_to_face_matrix[node_id].size(); ++l_face) { + // FaceId face_to_node_id = node_to_face_matrix[node_id][l_face]; + // if (face_to_node_id == face_id) { + // S(cell_dof_number[cell_id], face_dof_number[face_id]) -= + // w_rl(node_id, l_face) * a_ir; + // } + // } + // } + // } + // } + // } + // } + // } + // } + // } + // } + // } + // }, + // boundary_condition); + // } + // std::exit(0); + // 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]) { + 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]) { + std::cout << "TEST***********************" + << "\n"; + 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()); @@ -572,8 +728,65 @@ HeatDiamondScheme<Dimension>::HeatDiamondScheme( } } + 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>)) { + const auto& face_list = bc.faceList(); + 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]; + } + } + } + } + }, + boundary_condition); + } + + std::cout << S << '\n'; + + // for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) { + // if (primal_face_is_neumann[face_id]) { + // b[face_dof_number[face_id]] = 100; + // std::cout << "b[" << face_dof_number[face_id] << "] = " << b[face_dof_number[face_id]] << '\n'; + // } + // } + Vector<double> T{number_of_dof}; - T = 0; + T = 1; + T[6] = 2; + T[7] = 3; + T[8] = 4; + Vector AT = A * T; + for (size_t i = 0; i < T.size(); ++i) { + std::cout << " AT[" << i << "] = " << AT[i] << '\t'; + std::cout << " b[" << i << "] = " << b[i] << '\n'; + } BiCGStab{b, A, T, 1000, 1e-15};