diff --git a/src/scheme/ImplicitAcousticSolver.cpp b/src/scheme/ImplicitAcousticSolver.cpp index 7cfed87083e24a82ecdac253669fd58fa1bf382e..411c4112c0f1af52061ffb791094732cdd03f538 100644 --- a/src/scheme/ImplicitAcousticSolver.cpp +++ b/src/scheme/ImplicitAcousticSolver.cpp @@ -5,7 +5,9 @@ #include <mesh/MeshCellZone.hpp> #include <mesh/MeshFaceBoundary.hpp> #include <mesh/MeshFlatNodeBoundary.hpp> +#include <mesh/MeshLineNodeBoundary.hpp> #include <mesh/MeshNodeBoundary.hpp> +#include <scheme/AxisBoundaryConditionDescriptor.hpp> #include <scheme/DirichletBoundaryConditionDescriptor.hpp> #include <scheme/DiscreteFunctionP0.hpp> #include <scheme/DiscreteFunctionUtils.hpp> @@ -13,20 +15,28 @@ #include <scheme/IDiscreteFunctionDescriptor.hpp> #include <scheme/SymmetryBoundaryConditionDescriptor.hpp> +#include <mesh/ItemValueVariant.hpp> +#include <output/NamedItemValueVariant.hpp> +#include <output/VTKWriter.hpp> #include <utils/Timer.hpp> #include <variant> #include <vector> +// VTKWriter vtk_writer("imp/debug", 0); + +int count_newton = 0; +int count_Djr = 0; +int count_timestep = 0; + Timer solver_t; Timer get_A_t; Timer getF_t; Timer getGradF_t; Timer HJ_A_t; -static int count_getA = 0; -static int count_getF = 0; -static int count_getGradF = 0; +int count_getA = 0; +int count_getGradF = 0; template <size_t Dimension> double @@ -89,12 +99,13 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final using DiscreteScalarFunction = DiscreteFunctionP0<Dimension, const double>; using DiscreteVectorFunction = DiscreteFunctionP0<Dimension, const Rd>; + class AxisBoundaryCondition; class PressureBoundaryCondition; class SymmetryBoundaryCondition; class VelocityBoundaryCondition; - using BoundaryCondition = - std::variant<PressureBoundaryCondition, SymmetryBoundaryCondition, VelocityBoundaryCondition>; + using BoundaryCondition = std:: + variant<AxisBoundaryCondition, PressureBoundaryCondition, SymmetryBoundaryCondition, VelocityBoundaryCondition>; using BoundaryConditionList = std::vector<BoundaryCondition>; @@ -183,7 +194,6 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final Ajr(j, r) = tensorProduct(rho[j] * c[j] * Cjr_n(j, r), njr_n(j, r)); } }); - break; } case SolverType::Eucclhyd: { @@ -256,24 +266,61 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final Ar[node_id] = sum; }); - NodeValue<int> boundary_node_s(m_mesh.connectivity()); - boundary_node_s.fill(-1); + NodeValue<bool> has_boundary_condition{m_mesh.connectivity()}; + has_boundary_condition.fill(false); + // velocity bc for (const auto& boundary_condition : m_boundary_condition_list) { std::visit( [&](auto&& bc) { using T = std::decay_t<decltype(bc)>; if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { const auto& node_list = bc.nodeList(); - for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - const NodeId& node_id = node_list[i_node]; - boundary_node_s[node_id] = 1; - } + + parallel_for( + node_list.size(), PUGS_LAMBDA(const size_t i_node) { + const NodeId node_id = node_list[i_node]; + + if (not has_boundary_condition[node_id]) { + Ar[node_id] = identity; + + has_boundary_condition[node_id] = true; + } + }); } }, boundary_condition); } + if constexpr (Dimension > 1) { + // axis bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<AxisBoundaryCondition, T>) { + const Rd& t = bc.direction(); + + const Rdxd I = identity; + const Rdxd txt = tensorProduct(t, t); + + const Array<const NodeId>& node_list = bc.nodeList(); + + for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { + const NodeId& node_id = node_list[i_node]; + if (not has_boundary_condition[node_id]) { + Ar[node_id] = txt * Ar[node_id] * txt + (I - txt); + + has_boundary_condition[node_id] = true; + } + } + } + }, + boundary_condition); + } + } + + // symmetry bc for (const auto& boundary_condition : m_boundary_condition_list) { std::visit( [&](auto&& bc) { @@ -289,23 +336,12 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { const NodeId& node_id = node_list[i_node]; - if (boundary_node_s[node_id] != -1) { - } else { + if (not has_boundary_condition[node_id]) { Ar[node_id] = P * Ar[node_id] * P + nxn; + + has_boundary_condition[node_id] = true; } } - } else if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { - const auto& node_list = bc.nodeList(); - - parallel_for( - node_list.size(), PUGS_LAMBDA(size_t i_node) { - NodeId node_id = node_list[i_node]; - - Ar[node_id] = identity; - }); - } else if constexpr (std::is_same_v<PressureBoundaryCondition, T>) { - } else { - throw UnexpectedError("boundary condition not handled 1"); } }, boundary_condition); @@ -329,15 +365,15 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final int mapP(CellId j) const { - return (1 + Dimension) * m_implicit_cell_index[j]; - // return m_implicit_cell_index[j]; + // return (1 + Dimension) * m_implicit_cell_index[j]; + return m_implicit_cell_index[j]; } int mapU(size_t k, CellId j) const { - return (1 + Dimension) * m_implicit_cell_index[j] + k + 1; - // return m_number_of_implicit_cells + k + m_implicit_cell_index[j] * Dimension; + // return (1 + Dimension) * m_implicit_cell_index[j] + k + 1; + return m_number_of_implicit_cells + k + m_implicit_cell_index[j] * Dimension; } CRSMatrixDescriptor<double> @@ -425,34 +461,12 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final } } - NodeValue<int> boundary_node_s(m_mesh.connectivity()); - boundary_node_s.fill(-1); - - NodeValue<int> boundary_node_v(m_mesh.connectivity()); - boundary_node_v.fill(-1); - + // pressure bc for (const auto& boundary_condition : m_boundary_condition_list) { std::visit( [&](auto&& bc) { using T = std::decay_t<decltype(bc)>; - if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { - const auto& node_list = bc.nodeList(); - for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - const NodeId& node_id = node_list[i_node]; - boundary_node_s[node_id] = 1; - } - } - }, - boundary_condition); - } - - for (const auto& boundary_condition : m_boundary_condition_list) { - std::visit( - [&](auto&& bc) { - using T = std::decay_t<decltype(bc)>; - if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { - // no changes for velocity conditions - } else if constexpr (std::is_same_v<PressureBoundaryCondition, T>) { + if constexpr (std::is_same_v<PressureBoundaryCondition, T>) { // const auto& face_list = bc.faceList(); // const auto& face_local_numbers_in_their_cells = m_mesh.connectivity().faceLocalNumbersInTheirCells(); @@ -485,7 +499,91 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final // } // } // } - } else if constexpr (std::is_same_v<SymmetryBoundaryCondition, T>) { + } + }, + boundary_condition); + } + + NodeValue<bool> has_boundary_condition{m_mesh.connectivity()}; + has_boundary_condition.fill(false); + + // velocity bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { + const auto& node_list = bc.nodeList(); + + parallel_for( + node_list.size(), PUGS_LAMBDA(const size_t i_node) { + const NodeId node_id = node_list[i_node]; + if (not has_boundary_condition[node_id]) { + has_boundary_condition[node_id] = true; + } + }); + } + }, + boundary_condition); + } + + if constexpr (Dimension > 1) { + // axis bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<AxisBoundaryCondition, T>) { + const auto& node_list = bc.nodeList(); + + const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); + const auto& node_to_cell_matrix = m_mesh.connectivity().nodeToCellMatrix(); + const Rd& t = bc.direction(); + const Rdxd txt = tensorProduct(t, t); + + for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { + const NodeId& node_id = node_list[i_node]; + if (not has_boundary_condition[node_id]) { + const Rdxd inverse_Ar_times_txt = m_inv_Ar[node_id] * txt; + const auto& node_cell = node_to_cell_matrix[node_id]; + const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); + + for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { + for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { + const CellId id_cell_i = node_cell[cell_i]; + if (m_is_implicit_cell[id_cell_i]) { + const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; + const int i_index_u = mapU(i_dimension, id_cell_i); + for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { + const CellId id_cell_j = node_cell[cell_j]; + if (m_is_implicit_cell[id_cell_j]) { + const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; + const int j_index_p = mapP(id_cell_j); + + const Rd coef = + m_Ajr(id_cell_i, node_nb_in_i) * inverse_Ar_times_txt * m_Djr(id_cell_j, node_nb_in_j); + A(j_index_p, i_index_u) += coef[i_dimension]; + A(i_index_u, j_index_p) -= coef[i_dimension]; + } + } + } + } + } + has_boundary_condition[node_id] = true; + } + } + } + }, + boundary_condition); + } + } + + // symmetry bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<SymmetryBoundaryCondition, T>) { const auto& node_list = bc.nodeList(); const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); @@ -494,13 +592,11 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final const Rdxd I = identity; const Rdxd nxn = tensorProduct(n, n); const Rdxd P = I - nxn; - NodeValue<Rdxd> inverse_ArxP{m_mesh.connectivity()}; for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { const NodeId& node_id = node_list[i_node]; - if (boundary_node_s[node_id] != -1) { - } else { - inverse_ArxP[node_id] = m_inv_Ar[node_id] * P; + if (not has_boundary_condition[node_id]) { + const Rdxd inverse_ArxP = m_inv_Ar[node_id] * P; const auto& node_cell = node_to_cell_matrix[node_id]; const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); @@ -517,7 +613,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final const int j_index_p = mapP(id_cell_j); const Rd coef = - m_Ajr(id_cell_i, node_nb_in_i) * inverse_ArxP[node_id] * m_Djr(id_cell_j, node_nb_in_j); + m_Ajr(id_cell_i, node_nb_in_i) * inverse_ArxP * m_Djr(id_cell_j, node_nb_in_j); A(j_index_p, i_index_u) += coef[i_dimension]; A(i_index_u, j_index_p) -= coef[i_dimension]; } @@ -525,10 +621,9 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final } } } + has_boundary_condition[node_id] = true; } } - } else { - throw UnexpectedError("boundary condition not handled 2"); } }, boundary_condition); @@ -539,7 +634,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final } Vector<double> - _getU(const DiscreteScalarFunction& p, const DiscreteVectorFunction& u) + _getU(const CellValue<const double>& p, const CellValue<const Rd>& u) { Vector<double> Un{(Dimension + 1) * m_number_of_implicit_cells}; @@ -565,350 +660,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final } Vector<double> - _getGradJ(const Vector<double>& Un, - const Vector<double>& Uk, - const DiscreteScalarFunction& p, - const DiscreteScalarFunction& pi, - const DiscreteVectorFunction& u, - const double dt) - { - count_getF++; - static bool getF_is_started = false; - if (not getF_is_started) { - getF_is_started = true; - getF_t.stop(); - } - - getF_t.start(); - m_tau_iter = [&]() { - CellValue<double> computed_tau_iter(m_mesh.connectivity()); - parallel_for( - m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { - if (m_is_implicit_cell[j]) { - size_t k = mapP(j); - computed_tau_iter[j] = m_g_1_exp_S_Cv_inv_g[j] * std::pow(-Uk[k] + pi[j], -m_inv_gamma[j]); - } - }); - return computed_tau_iter; - }(); - - getF_t.pause(); - - Vector<double> computed_gradJ{(Dimension + 1) * m_number_of_implicit_cells}; - computed_gradJ = zero; - const auto& node_to_cell_matrix = m_mesh.connectivity().nodeToCellMatrix(); - const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); - - auto is_boundary_node = m_mesh.connectivity().isBoundaryNode(); - for (NodeId node_id = 0; node_id < m_mesh.numberOfNodes(); ++node_id) { - if (not is_boundary_node[node_id]) { - const auto& node_cell = node_to_cell_matrix[node_id]; - const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); - Rd sum_Djrpj = zero; - Rd sum_Ajruj = zero; - Rd Uk_i = zero; - Rd Uk_j = zero; - for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { - const CellId id_cell_i = node_cell[cell_i]; - if (m_is_implicit_cell[id_cell_i]) { - const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; - const size_t i_index_p = mapP(id_cell_i); - sum_Djrpj += Uk[i_index_p] * m_Djr(id_cell_i, node_nb_in_i); - - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - const size_t i_index_u = mapU(i_dimension, id_cell_i); - Uk_i[i_dimension] = Uk[i_index_u]; - } - sum_Ajruj += m_Ajr(id_cell_i, node_nb_in_i) * Uk_i; - } - } - - for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { - const CellId id_cell_j = node_cell[cell_j]; - if (m_is_implicit_cell[id_cell_j]) { - const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; - const size_t j_index_p = mapP(id_cell_j); - - computed_gradJ[j_index_p] += dot(m_Djr(id_cell_j, node_nb_in_j), m_inv_Ar[node_id] * sum_Djrpj); - - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - const size_t j_index_u = mapU(i_dimension, id_cell_j); - Uk_j[i_dimension] = Uk[j_index_u]; - } - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - const size_t j_index_u = mapU(i_dimension, id_cell_j); - computed_gradJ[j_index_u] += (-m_Ajr(id_cell_j, node_nb_in_j) * m_inv_Ar[node_id] * sum_Ajruj + - m_Ajr(id_cell_j, node_nb_in_j) * Uk_j)[i_dimension]; - } - } - } - } - } - - const double inv_dt = 1. / dt; - for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) { - if (m_is_implicit_cell[cell_id]) { - size_t j_index_p = mapP(cell_id); - computed_gradJ[j_index_p] += (inv_dt * m_Mj[cell_id]) * (m_tau_iter[cell_id] - m_tau[cell_id]); - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - size_t j_index_u = mapU(i_dimension, cell_id); - computed_gradJ[j_index_u] += (inv_dt * m_Mj[cell_id]) * (Uk[j_index_u] - Un[j_index_u]); - } - } - } - - for (NodeId node_id = 0; node_id < m_mesh.numberOfNodes(); ++node_id) { - const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); - if (m_is_implicit_node[node_id]) { - if (not is_boundary_node[node_id]) { - const auto& node_cells = node_to_cell_matrix[node_id]; - Rd sum_Djrpj_exp = zero; - Rd sum_Ajruj_exp = zero; - for (size_t i_cell = 0; i_cell < node_cells.size(); ++i_cell) { - if (not m_is_implicit_cell[node_cells[i_cell]]) { - const size_t node_nb_in_i = node_local_number_in_its_cells[i_cell]; - sum_Djrpj_exp += p[node_cells[i_cell]] * m_Djr(node_cells[i_cell], node_nb_in_i); - sum_Ajruj_exp += m_Ajr(node_cells[i_cell], node_nb_in_i) * u[node_cells[i_cell]]; - } - } - for (size_t j_cell = 0; j_cell < node_cells.size(); ++j_cell) { - const CellId id_cell_j = node_cells[j_cell]; - if (m_is_implicit_cell[id_cell_j]) { - const size_t node_nb_in_j = node_local_number_in_its_cells[j_cell]; - const size_t j_index_p = mapP(id_cell_j); - computed_gradJ[j_index_p] -= dot(m_Djr(id_cell_j, node_nb_in_j), m_inv_Ar[node_id] * sum_Djrpj_exp) + - dot(m_Djr(id_cell_j, node_nb_in_j), m_inv_Ar[node_id] * sum_Ajruj_exp); - - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - const size_t j_index_u = mapU(i_dimension, id_cell_j); - computed_gradJ[j_index_u] -= - (m_Ajr(id_cell_j, node_nb_in_j) * m_inv_Ar[node_id] * sum_Djrpj_exp + - m_Ajr(id_cell_j, node_nb_in_j) * m_inv_Ar[node_id] * sum_Ajruj_exp)[i_dimension]; - } - } - } - } - } - } - - NodeValue<int> boundary_node_s(m_mesh.connectivity()); - boundary_node_s.fill(-1); - - NodeValue<int> boundary_node_v(m_mesh.connectivity()); - boundary_node_v.fill(-1); - - for (const auto& boundary_condition : m_boundary_condition_list) { - std::visit( - [&](auto&& bc) { - using T = std::decay_t<decltype(bc)>; - if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { - const auto& node_list = bc.nodeList(); - for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - const NodeId& node_id = node_list[i_node]; - boundary_node_s[node_id] = 1; - } - } - }, - boundary_condition); - } - - for (const auto& boundary_condition : m_boundary_condition_list) { - std::visit( - [&](auto&& bc) { - using T = std::decay_t<decltype(bc)>; - - // else if constexpr (std::is_same_v<PressureBoundaryCondition, T>) { - // const auto& node_list = bc.faceList(); - // const auto& value_list = bc.valueList(); - - // MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(m_mesh); - // const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); - // const auto& node_to_cell_matrix = m_mesh.connectivity().nodeToCellMatrix(); - // Rd sum_Djrpext = zero; - - // for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - // const NodeId& node_id = node_list[i_node]; - // // if (m_is_implicit_node[node_id]) { - // const auto& node_cell = node_to_cell_matrix[node_id]; - // for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { - // const CellId id_cell_i = node_cell[cell_i]; - // if (m_is_implicit_cell[id_cell_i]) { - // const auto& node_local_number_in_its_cells = - // node_local_numbers_in_their_cells.itemArray(node_id); const size_t node_nb_in_i = - // node_local_number_in_its_cells[cell_i]; - - // sum_Djrpext += value_list[i_node] * m_Djr(id_cell_i, node_nb_in_i); - // } - // } - // for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { - // const CellId id_cell_j = node_cell[cell_j]; - // if (m_is_implicit_cell[id_cell_j]) { - // const auto& node_local_number_in_its_cells = - // node_local_numbers_in_their_cells.itemArray(node_id); const size_t node_nb_in_j = - // node_local_number_in_its_cells[cell_j]; int index_p = - // mapP(id_cell_j); computed_gradJ[index_p] += dot(m_Djr(id_cell_j, node_nb_in_j), m_inv_Ar[node_id] - // * sum_Djrpext); for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - // int index_u = mapU(i_dimension, id_cell_j); - // computed_gradJ[index_u] += - // (m_Ajr(id_cell_j, node_nb_in_j) * m_inv_Ar[node_id] * sum_Djrpext)[i_dimension]; - // } - // } - // } - // } - // } - if constexpr (std::is_same_v<SymmetryBoundaryCondition, T>) { - const auto& node_list = bc.nodeList(); - const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); - const auto& node_to_cell_matrix = m_mesh.connectivity().nodeToCellMatrix(); - const Rd& n = bc.outgoingNormal(); - const Rdxd I = identity; - const Rdxd nxn = tensorProduct(n, n); - const Rdxd P = I - nxn; - NodeValue<Rdxd> inverse_ArxP{m_mesh.connectivity()}; - Rd Uk_j = zero; - - for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - const NodeId& node_id = node_list[i_node]; - if (boundary_node_s[node_id] != -1) { - } else { - const auto& node_cell = node_to_cell_matrix[node_id]; - - inverse_ArxP[node_id] = m_inv_Ar[node_id] * P; - Rd sum_Djrpj = zero; - Rd sum_Ajruj = zero; - Rd sum_Djrpj_exp = zero; - Rd sum_Ajruj_exp = zero; - Rd Uk_i = zero; - const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); - - for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { - const CellId id_cell_i = node_cell[cell_i]; - if (m_is_implicit_cell[id_cell_i]) { - const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; - const size_t i_index_p = mapP(id_cell_i); - sum_Djrpj += Uk[i_index_p] * m_Djr(id_cell_i, node_nb_in_i); - - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - const size_t i_index_u = mapU(i_dimension, id_cell_i); - Uk_i[i_dimension] = Uk[i_index_u]; - } - sum_Ajruj += m_Ajr(id_cell_i, node_nb_in_i) * Uk_i; - } - } - - for (size_t i_cell = 0; i_cell < node_cell.size(); ++i_cell) { - if (not m_is_implicit_cell[node_cell[i_cell]]) { - const size_t node_nb_in_i = node_local_number_in_its_cells[i_cell]; - sum_Djrpj_exp += p[node_cell[i_cell]] * m_Djr(node_cell[i_cell], node_nb_in_i); - sum_Ajruj_exp += m_Ajr(node_cell[i_cell], node_nb_in_i) * u[node_cell[i_cell]]; - } - } - - for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { - const CellId id_cell_j = node_cell[cell_j]; - if (m_is_implicit_cell[id_cell_j]) { - const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; - - int index_p = mapP(id_cell_j); - computed_gradJ[index_p] += - dot(m_Djr(id_cell_j, node_nb_in_j), inverse_ArxP[node_id] * sum_Djrpj) - - dot(m_Djr(id_cell_j, node_nb_in_j), inverse_ArxP[node_id] * sum_Djrpj_exp) - - dot(m_Djr(id_cell_j, node_nb_in_j), inverse_ArxP[node_id] * sum_Ajruj_exp); - ; - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - int j_index_u = mapU(i_dimension, id_cell_j); - Uk_j[i_dimension] = Uk[j_index_u]; - } - - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - int index_u = mapU(i_dimension, id_cell_j); - computed_gradJ[index_u] += - (-m_Ajr(id_cell_j, node_nb_in_j) * inverse_ArxP[node_id] * sum_Ajruj + - m_Ajr(id_cell_j, node_nb_in_j) * Uk_j)[i_dimension] - - (m_Ajr(id_cell_j, node_nb_in_j) * inverse_ArxP[node_id] * sum_Djrpj_exp + - m_Ajr(id_cell_j, node_nb_in_j) * inverse_ArxP[node_id] * sum_Ajruj_exp)[i_dimension]; - } - } - } - } - } - } else if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { - const auto& node_list = bc.nodeList(); - const auto& value_list = bc.valueList(); - - const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); - const auto& node_to_cell_matrix = m_mesh.connectivity().nodeToCellMatrix(); - - for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - const NodeId& node_id = node_list[i_node]; - if (boundary_node_v[node_id] != -1) { - } else { - boundary_node_v[node_id] = 1; - // if (m_is_implicit_node[node_id]) { - const auto& node_cell = node_to_cell_matrix[node_id]; - Rd Uk_i = zero; - for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { - const CellId id_cell_i = node_cell[cell_i]; - if (m_is_implicit_cell[id_cell_i]) { - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - int i_index_u = mapU(i_dimension, id_cell_i); - Uk_i[i_dimension] = Uk[i_index_u]; - } - } - } - - for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { - const CellId id_cell_i = node_cell[cell_i]; - if (m_is_implicit_cell[id_cell_i]) { - const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); - const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; - int i_index_p = mapP(id_cell_i); - computed_gradJ[i_index_p] += -dot(m_Djr(id_cell_i, node_nb_in_i), value_list[i_node]); - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - int i_index_u = mapU(i_dimension, id_cell_i); - computed_gradJ[i_index_u] += - (m_Ajr(id_cell_i, node_nb_in_i) * (Uk_i - value_list[i_node]))[i_dimension]; - } - } - } - } - } - } else if constexpr (std::is_same_v<PressureBoundaryCondition, T>) { - } else { - throw UnexpectedError("boundary condition not handled 3"); - } - }, - boundary_condition); - } - return computed_gradJ; - } - - Vector<double> - _getF(const CRSMatrix<double, int>& A, - const Vector<double>& Un, - const Vector<double>& Uk, - const DiscreteScalarFunction& p, - const DiscreteScalarFunction& pi, - const DiscreteVectorFunction& u, - const double dt) - { - Vector<double> gradJ = this->_getGradJ(Un, Uk, p, pi, u, dt); - - Vector<double> AU = A * Uk; - - Vector<double> F = gradJ - AU; - - return F; - } - - Vector<double> - _getF_new(const CRSMatrix<double, int>& A, - const Vector<double>& Un, - const Vector<double>& Uk, - const DiscreteScalarFunction& p, - const DiscreteScalarFunction& pi, - const DiscreteVectorFunction& u, - const double dt) + _getF(const Vector<double>& Un, const Vector<double>& Uk, const DiscreteScalarFunction& pi, const double dt) { const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix(); @@ -1038,6 +790,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final const int i_index_p = mapP(cell_id); Hess_J(i_index_p, i_index_p) = (inv_dt * m_Mj[cell_id]) * m_inv_gamma[cell_id] * m_tau_iter[cell_id] / (-Uk[i_index_p] + pi[cell_id]); + for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { const int i_index_u = mapU(i_dimension, cell_id); Hess_J(i_index_u, i_index_u) = inv_dt * m_Mj[cell_id]; @@ -1047,12 +800,29 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final getGradF_t.start(); for (NodeId node_id = 0; node_id < m_mesh.numberOfNodes(); ++node_id) { + const auto& node_cell = node_to_cell_matrix[node_id]; + const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); + + for (size_t j_cell = 0; j_cell < node_cell.size(); ++j_cell) { + const CellId cell_id_j = node_cell[j_cell]; + if (m_is_implicit_cell[cell_id_j]) { + const size_t node_nb_in_j_cell = node_local_number_in_its_cells[j_cell]; + + const auto Ajr = m_Ajr(cell_id_j, node_nb_in_j_cell); + + for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { + const int i_index_u = mapU(i_dimension, cell_id_j); + for (size_t j_dimension = 0; j_dimension < Dimension; ++j_dimension) { + const int j_index_u = mapU(j_dimension, cell_id_j); + Hess_J(i_index_u, j_index_u) += Ajr(i_dimension, j_dimension); + } + } + } + } + if (not is_boundary_node[node_id]) { const auto& inv_Ar = m_inv_Ar[node_id]; - const auto& node_cell = node_to_cell_matrix[node_id]; - const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); - for (size_t j_cell = 0; j_cell < node_cell.size(); ++j_cell) { const CellId cell_id_j = node_cell[j_cell]; if (m_is_implicit_cell[cell_id_j]) { @@ -1066,24 +836,11 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final if (m_is_implicit_cell[cell_id_i]) { const size_t node_nb_in_cell_i = node_local_number_in_its_cells[i_cell]; const int i_index_p = mapP(cell_id_i); - Hess_J(j_index_p, i_index_p) += dot(invArDjr, m_Djr(cell_id_i, node_nb_in_cell_i)); + Hess_J(i_index_p, j_index_p) += dot(m_Djr(cell_id_i, node_nb_in_cell_i), invArDjr); } } } } - for (size_t j_cell = 0; j_cell < node_cell.size(); ++j_cell) { - const CellId cell_id_j = node_cell[j_cell]; - if (m_is_implicit_cell[cell_id_j]) { - const size_t node_nb_in_j_cell = node_local_number_in_its_cells[j_cell]; - - const auto Ajr = m_Ajr(cell_id_j, node_nb_in_j_cell); - - for (size_t j_dimension = 0; j_dimension < Dimension; ++j_dimension) { - const int j_index_u = mapU(j_dimension, cell_id_j); - Hess_J(j_index_u, j_index_u) += Ajr(j_dimension, j_dimension); - } - } - } for (size_t j_cell = 0; j_cell < node_cell.size(); ++j_cell) { const CellId cell_id_j = node_cell[j_cell]; @@ -1102,43 +859,186 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final for (size_t j_dimension = 0; j_dimension < Dimension; ++j_dimension) { const int index_u_j = mapU(j_dimension, cell_id_j); - for (size_t j_dimension = 0; j_dimension < Dimension; ++j_dimension) { - const int index_u_i = mapU(j_dimension, cell_id_i); - Hess_J(index_u_j, index_u_i) -= Ajr_invAr_Air(j_dimension, j_dimension); + for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { + const int index_u_i = mapU(i_dimension, cell_id_i); + Hess_J(index_u_j, index_u_i) -= Ajr_invAr_Air(j_dimension, i_dimension); + } + } + } + } + } + } + } + } + getGradF_t.pause(); + + // presure bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<PressureBoundaryCondition, T>) { + // const auto& node_list = bc.faceList(); + + // const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); + // const auto& node_to_cell_matrix = m_mesh.connectivity().nodeToCellMatrix(); + + // for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { + // const NodeId& node_id = node_list[i_node]; + // // if (m_is_implicit_node[node_id]) { + // const auto& node_cell = node_to_cell_matrix[node_id]; + + // for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { + // const CellId id_cell_i = node_cell[cell_i]; + // if (m_is_implicit_cell[id_cell_i]) { + // const auto& node_local_number_in_its_cells = + // node_local_numbers_in_their_cells.itemArray(node_id); + + // const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; + // const int i_index_p = mapP(id_cell_i); + + // for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { + // const CellId id_cell_j = node_cell[cell_j]; + // if (m_is_implicit_cell[id_cell_j]) { + // const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; + // const int j_index_p = mapP(id_cell_j); + + // Hess_J(i_index_p, j_index_p) += + // dot(m_Djr(id_cell_i, node_nb_in_i), m_inv_Ar[node_id] * m_Djr(id_cell_j, node_nb_in_j)); + // } + // } + // } + // } + // for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { + // const CellId id_cell_i = node_cell[cell_i]; + // if (m_is_implicit_cell[id_cell_i]) { + // const auto& node_local_number_in_its_cells = + // node_local_numbers_in_their_cells.itemArray(node_id); + + // const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; + // for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { + // const int i_index_u = mapU(i_dimension, id_cell_i); + + // Hess_J(i_index_u, i_index_u) += m_Ajr(id_cell_i, node_nb_in_i)(i_dimension, i_dimension); + + // for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { + // const CellId id_cell_j = node_cell[cell_j]; + // if (m_is_implicit_cell[id_cell_j]) { + // const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; + // for (size_t j_dimension = 0; j_dimension < Dimension; ++j_dimension) { + // const int j_index_u = mapU(j_dimension, id_cell_j); + + // Hess_J(i_index_u, j_index_u) += -(m_Ajr(id_cell_i, node_nb_in_i) * m_inv_Ar[node_id] * + // m_Ajr(id_cell_j, node_nb_in_j))(i_dimension, + // j_dimension); + // } + // } + // } + // } + // } + // } + // } + } + }, + boundary_condition); + } + + NodeValue<bool> has_boundary_condition{m_mesh.connectivity()}; + has_boundary_condition.fill(false); + + // velocity bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { + const auto& node_list = bc.nodeList(); + for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { + const NodeId node_id = node_list[i_node]; + has_boundary_condition[node_id] = true; + } + } + }, + boundary_condition); + } + + if constexpr (Dimension > 1) { + // axis bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<AxisBoundaryCondition, T>) { + const auto& node_list = bc.nodeList(); + + const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); + const auto& node_to_cell_matrix = m_mesh.connectivity().nodeToCellMatrix(); + const Rd& t = bc.direction(); + const Rdxd txt = tensorProduct(t, t); + + for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { + const NodeId& node_id = node_list[i_node]; + + if (not has_boundary_condition[node_id]) { + const Rdxd inverse_Ar_times_txt = m_inv_Ar[node_id] * txt; + + const auto& node_cell = node_to_cell_matrix[node_id]; + + for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { + const CellId id_cell_i = node_cell[cell_i]; + if (m_is_implicit_cell[id_cell_i]) { + const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); + const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; + + for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { + const int i_index_u = mapU(i_dimension, id_cell_i); + + for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { + const CellId id_cell_j = node_cell[cell_j]; + if (m_is_implicit_cell[id_cell_j]) { + const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; + + for (size_t j_dimension = 0; j_dimension < Dimension; ++j_dimension) { + const int j_index_u = mapU(j_dimension, id_cell_j); + Hess_J(i_index_u, j_index_u) += + (-m_Ajr(id_cell_i, node_nb_in_i) * inverse_Ar_times_txt * + m_Ajr(id_cell_j, node_nb_in_j))(i_dimension, j_dimension); + } + } + } + } + } + } + + for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { + const CellId id_cell_i = node_cell[cell_i]; + if (m_is_implicit_cell[id_cell_i]) { + const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); + const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; + + const int i_index_p = mapP(id_cell_i); + + for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { + const CellId id_cell_j = node_cell[cell_j]; + if (m_is_implicit_cell[id_cell_j]) { + const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; + const int j_index_p = mapP(id_cell_j); + Hess_J(i_index_p, j_index_p) += + dot(m_Djr(id_cell_i, node_nb_in_i), inverse_Ar_times_txt * m_Djr(id_cell_j, node_nb_in_j)); + } + } + } } + has_boundary_condition[node_id] = true; } } } - } - } + }, + boundary_condition); } } - getGradF_t.pause(); - - // NodeValue<int> boundary_node_sym(m_mesh.connectivity()); - // boundary_node_sym.fill(-1); - - NodeValue<int> boundary_node_s(m_mesh.connectivity()); - boundary_node_s.fill(-1); - - NodeValue<int> boundary_node_v(m_mesh.connectivity()); - boundary_node_v.fill(-1); - - for (const auto& boundary_condition : m_boundary_condition_list) { - std::visit( - [&](auto&& bc) { - using T = std::decay_t<decltype(bc)>; - if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { - const auto& node_list = bc.nodeList(); - for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - const NodeId& node_id = node_list[i_node]; - boundary_node_s[node_id] = 1; - } - } - }, - boundary_condition); - } + // symmetry bc for (const auto& boundary_condition : m_boundary_condition_list) { std::visit( [&](auto&& bc) { @@ -1152,30 +1052,15 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final const Rdxd I = identity; const Rdxd nxn = tensorProduct(n, n); const Rdxd P = I - nxn; - NodeValue<Rdxd> inverse_ArxP{m_mesh.connectivity()}; for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { const NodeId& node_id = node_list[i_node]; - if (boundary_node_s[node_id] != -1) { - } else { - inverse_ArxP[node_id] = m_inv_Ar[node_id] * P; + if (not has_boundary_condition[node_id]) { + const Rdxd inverse_ArxP = m_inv_Ar[node_id] * P; const auto& node_cell = node_to_cell_matrix[node_id]; - for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { - const CellId id_cell_i = node_cell[cell_i]; - if (m_is_implicit_cell[id_cell_i]) { - const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); - const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; - - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - const int i_index_u = mapU(i_dimension, id_cell_i); - Hess_J(i_index_u, i_index_u) += m_Ajr(id_cell_i, node_nb_in_i)(i_dimension, i_dimension); - } - } - } - for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { const CellId id_cell_i = node_cell[cell_i]; if (m_is_implicit_cell[id_cell_i]) { @@ -1192,7 +1077,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final for (size_t j_dimension = 0; j_dimension < Dimension; ++j_dimension) { const int j_index_u = mapU(j_dimension, id_cell_j); - Hess_J(i_index_u, j_index_u) += (-m_Ajr(id_cell_i, node_nb_in_i) * inverse_ArxP[node_id] * + Hess_J(i_index_u, j_index_u) += (-m_Ajr(id_cell_i, node_nb_in_i) * inverse_ArxP * m_Ajr(id_cell_j, node_nb_in_j))(i_dimension, j_dimension); } } @@ -1215,103 +1100,14 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; const int j_index_p = mapP(id_cell_j); Hess_J(i_index_p, j_index_p) += - dot(m_Djr(id_cell_i, node_nb_in_i), inverse_ArxP[node_id] * m_Djr(id_cell_j, node_nb_in_j)); + dot(m_Djr(id_cell_i, node_nb_in_i), inverse_ArxP * m_Djr(id_cell_j, node_nb_in_j)); } } } } + has_boundary_condition[node_id] = true; } } - } else if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { - const auto& node_list = bc.nodeList(); - const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); - const auto& node_to_cell_matrix = m_mesh.connectivity().nodeToCellMatrix(); - - for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - const NodeId& node_id = node_list[i_node]; - if (boundary_node_v[node_id] != -1) { - } else { - boundary_node_v[node_id] = 1; - - // if (m_is_implicit_node[node_id]) { - const auto& node_cell = node_to_cell_matrix[node_id]; - for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { - const CellId id_cell_j = node_cell[cell_j]; - if (m_is_implicit_cell[id_cell_j]) { - const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id); - for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - int i_index_u = mapU(i_dimension, id_cell_j); - - Hess_J(i_index_u, i_index_u) += - m_Ajr(id_cell_j, node_local_number_in_its_cells[cell_j])(i_dimension, i_dimension); - } - } - } - } - } - } else if constexpr (std::is_same_v<PressureBoundaryCondition, T>) { - // const auto& node_list = bc.faceList(); - - // const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells(); - // const auto& node_to_cell_matrix = m_mesh.connectivity().nodeToCellMatrix(); - - // for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { - // const NodeId& node_id = node_list[i_node]; - // // if (m_is_implicit_node[node_id]) { - // const auto& node_cell = node_to_cell_matrix[node_id]; - - // for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { - // const CellId id_cell_i = node_cell[cell_i]; - // if (m_is_implicit_cell[id_cell_i]) { - // const auto& node_local_number_in_its_cells = - // node_local_numbers_in_their_cells.itemArray(node_id); - - // const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; - // const int i_index_p = mapP(id_cell_i); - - // for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { - // const CellId id_cell_j = node_cell[cell_j]; - // if (m_is_implicit_cell[id_cell_j]) { - // const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; - // const int j_index_p = mapP(id_cell_j); - - // Hess_J(i_index_p, j_index_p) += - // dot(m_Djr(id_cell_i, node_nb_in_i), m_inv_Ar[node_id] * m_Djr(id_cell_j, node_nb_in_j)); - // } - // } - // } - // } - // for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) { - // const CellId id_cell_i = node_cell[cell_i]; - // if (m_is_implicit_cell[id_cell_i]) { - // const auto& node_local_number_in_its_cells = - // node_local_numbers_in_their_cells.itemArray(node_id); - - // const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i]; - // for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) { - // const int i_index_u = mapU(i_dimension, id_cell_i); - - // Hess_J(i_index_u, i_index_u) += m_Ajr(id_cell_i, node_nb_in_i)(i_dimension, i_dimension); - - // for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) { - // const CellId id_cell_j = node_cell[cell_j]; - // if (m_is_implicit_cell[id_cell_j]) { - // const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j]; - // for (size_t j_dimension = 0; j_dimension < Dimension; ++j_dimension) { - // const int j_index_u = mapU(j_dimension, id_cell_j); - - // Hess_J(i_index_u, j_index_u) += -(m_Ajr(id_cell_i, node_nb_in_i) * m_inv_Ar[node_id] * - // m_Ajr(id_cell_j, node_nb_in_j))(i_dimension, - // j_dimension); - // } - // } - // } - // } - // } - // } - // } - } else { - throw UnexpectedError("boundary condition not handled 4"); } }, boundary_condition); @@ -1337,7 +1133,25 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final CRSMatrix Hess_J_crs = Hess_J.getCRSMatrix(); + // std::cout << "Hess J = " << Hess_J_crs << '\n'; + CRSMatrix gradient_f = Hess_J_crs - A; + + // Vector<double> x(gradient_f.numberOfRows()); + // Vector<double> y(gradient_f.numberOfRows()); + // double max_err = 0; + // for (size_t i = 0; i < gradient_f.numberOfRows(); ++i) { + // x.fill(0); + // x[i] = 1; + // for (size_t j = 0; j < gradient_f.numberOfRows(); ++j) { + // y.fill(0); + // y[j] = 1; + + // max_err = std::max(max_err, std::abs(dot(x, gradient_f * y) - dot(y, gradient_f * x))); + // } + // } + // std::cout << "MAX NON SYM=" << rang::fgB::cyan << max_err << rang::fg::reset << '\n'; + HJ_A_t.pause(); return gradient_f; @@ -1353,6 +1167,18 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final bool is_valid_boundary_condition = true; switch (bc_descriptor->type()) { + case IBoundaryConditionDescriptor::Type::axis: { + if constexpr (Dimension == 1) { + throw NormalError("Axis boundary condition makes no sense in dimension 1"); + } else { + const AxisBoundaryConditionDescriptor& axis_bc_descriptor = + dynamic_cast<const AxisBoundaryConditionDescriptor&>(*bc_descriptor); + + bc_list.push_back( + AxisBoundaryCondition{getMeshLineNodeBoundary(*mesh, axis_bc_descriptor.boundaryDescriptor())}); + } + break; + } case IBoundaryConditionDescriptor::Type::symmetry: { const SymmetryBoundaryConditionDescriptor& sym_bc_descriptor = dynamic_cast<const SymmetryBoundaryConditionDescriptor&>(*bc_descriptor); @@ -1480,12 +1306,12 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final return implicit_node_index; }(); - std::cout << "building A: "; + std::cout << "building A: " << std::flush; const CRSMatrix A = this->_getA().getCRSMatrix(); - std::cout << "done\n"; + std::cout << "done\n" << std::flush; - Vector<double> Un = this->_getU(p, u); - Vector<double> Uk = copy(Un); + Vector<double> Un = this->_getU(p.cellValues(), u.cellValues()); + Vector<double> Uk = this->_getU(m_predicted_p, m_predicted_u); int nb_iter = 0; double norm_inf_sol; @@ -1501,17 +1327,12 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final if (m_number_of_implicit_cells > 0) { do { nb_iter++; - // Vector<double> f_old = this->_getF(A, Un, Uk, p, pi, u, dt); - Vector<double> f = this->_getF_new(A, Un, Uk, p, pi, u, dt); - std::cout << "building gradf: "; - CRSMatrix<double> gradient_f = this->_getGradientF(A, Uk, pi, dt); - std::cout << " done\n"; + Vector<double> f = this->_getF(Un, Uk, pi, dt); - // std::cout << "grad f = " << gradient_f << '\n'; - // std::cout << "f=" << f << '\n'; - std::cout << " -> f: [" << min(f) << ", " << max(f) << "]\n"; - // std::cout << "grad f=" << gradient_f << '\n'; + std::cout << "building gradf: " << std::flush; + CRSMatrix<double> gradient_f = this->_getGradientF(A, Uk, pi, dt); + std::cout << "done\n" << std::flush; auto l2Norm = [](const Vector<double>& x) { double sum2 = 0; @@ -1532,15 +1353,24 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final solver_t.start(); LinearSolver solver; + std::cout << "solving linear system: " << std::flush; solver.solveLocalSystem(gradient_f, sol, f); + std::cout << "done\n" << std::flush; solver_t.pause(); - std::cout << " -> sol: [" << min(sol) << ", " << max(sol) << "]\n"; - std::cout << "l2Norm(f) = " << l2Norm(f) << '\n'; - std::cout << "l2Norm(sol) = " << l2Norm(sol) << '\n'; std::cout << rang::style::bold << "norm resid = " << l2Norm(f - gradient_f * sol) << rang::style::reset << '\n'; - // std::exit(0); - Vector<double> U_next = Uk - 0.2 * sol; + double theta = 1; + + for (CellId cell_id = 0; cell_id < m_number_of_implicit_cells; ++cell_id) { + size_t k = mapP(cell_id); + if (-Uk[k] + theta * sol[k] < -pi[cell_id]) { + double new_theta = 0.5 * (Uk[k] - pi[cell_id]) / sol[k]; + std::cout << "theta: " << theta << " -> " << new_theta << '\n'; + theta = new_theta; + } + } + + Vector<double> U_next = Uk - theta * sol; Array<const double> abs_sol = [&]() { Array<double> compute_abs_sol{sol.size()}; @@ -1565,21 +1395,21 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final U_next[k] = Uk[k]; } } - if (neg_pressure_count > 0) { - std::cout << rang::fgB::magenta << "p est negatif sur " << neg_pressure_count - << " mailles min=" << min_pressure << rang::fg::reset << '\n'; - std::exit(0); - } - // Uk -= sol; - // if (neg_pressure) { - // std::cout << "HAS NEG PRESSURE, RELAXING\n"; - // Uk -= 0.01 * sol; - // } else { - // Uk -= sol; - // } Uk = U_next; + // if ((count_newton == 0) and (count_Djr == 0) and (count_timestep == 0)) { + // auto newt_mesh = std::make_shared<MeshType>(m_mesh.shared_connectivity(), m_mesh.xr()); + // double pseudo_time = 1E-8 * count_newton + 1E-3 * count_Djr + count_timestep; + + // std::vector<std::shared_ptr<const INamedDiscreteData>> output_list; + // output_list.push_back( + // std::make_shared<NamedItemValueVariant>(std::make_shared<ItemValueVariant>(m_predicted_p), + // "predicted_p")); + + // vtk_writer.writeOnMeshForced(newt_mesh, output_list, pseudo_time); + // } + m_predicted_u = [&] { CellValue<Rd> predicted_u = copy(u.cellValues()); for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) { @@ -1590,7 +1420,6 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final } predicted_u[cell_id] = vector_u; } - // std::cout << "u[" << cell_id << "]=" << predicted_u[cell_id] << '\n'; } return predicted_u; }(); @@ -1601,12 +1430,32 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final if (m_is_implicit_cell[cell_id]) { predicted_p[cell_id] = -Uk[mapP(cell_id)]; } - // std::cout << "p[" << cell_id << "]=" << predicted_p[cell_id] << '\n'; } return predicted_p; }(); - } while ((norm_inf_sol > 1e-15 * norm_inf_Un) or (nb_iter < 100)); + NodeValue<const Rd> ur = _getUr(); + + NodeValue<Rd> newton_xr{m_mesh.connectivity()}; + for (NodeId node_id = 0; node_id < m_mesh.numberOfNodes(); ++node_id) { + newton_xr[node_id] = m_mesh.xr()[node_id] + dt * ur[node_id]; + } + + auto newt_mesh = std::make_shared<MeshType>(m_mesh.shared_connectivity(), newton_xr); + ++count_newton; + // double pseudo_time = 1E-4 * count_newton + 1E-2 * count_Djr + count_timestep; + + // std::vector<std::shared_ptr<const INamedDiscreteData>> output_list; + // output_list.push_back( + // std::make_shared<NamedItemValueVariant>(std::make_shared<ItemValueVariant>(m_predicted_p), "predicted_p")); + + // vtk_writer.writeOnMeshForced(newt_mesh, output_list, pseudo_time); + + if (neg_pressure_count > 0) { + std::cout << rang::fgB::magenta << "p est negatif sur " << neg_pressure_count + << " mailles min=" << min_pressure << rang::fg::reset << '\n'; + } + } while ((norm_inf_sol > 1e-12 * norm_inf_Un) and (nb_iter < 1000)); } for (CellId j = 0; j < m_mesh.numberOfCells(); ++j) { @@ -1640,6 +1489,32 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final b[r] = br; }); + NodeValue<bool> has_boundary_condition{m_mesh.connectivity()}; + has_boundary_condition.fill(false); + + // velocity bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { + const auto& node_list = bc.nodeList(); + const auto& value_list = bc.valueList(); + + parallel_for( + node_list.size(), PUGS_LAMBDA(const size_t i_node) { + const NodeId node_id = node_list[i_node]; + const auto& value = value_list[i_node]; + b[node_id] = value; + + has_boundary_condition[node_id] = true; + }); + } + }, + boundary_condition); + } + + // pressure bc for (const auto& boundary_condition : m_boundary_condition_list) { std::visit( [&](auto&& bc) { @@ -1660,8 +1535,8 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final const auto& node_cell_list = node_to_cell_matrix[node_id]; Assert(node_cell_list.size() == 1); - CellId node_cell_id = node_cell_list[0]; - size_t node_local_number_in_cell = node_local_numbers_in_their_cells(node_id, 0); + const CellId node_cell_id = node_cell_list[0]; + const size_t node_local_number_in_cell = node_local_numbers_in_their_cells(node_id, 0); b[node_id] -= value_list[i_node] * Cjr(node_cell_id, node_local_number_in_cell); }); @@ -1680,8 +1555,8 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final const auto& face_cell_list = face_to_cell_matrix[face_id]; Assert(face_cell_list.size() == 1); - CellId face_cell_id = face_cell_list[0]; - size_t face_local_number_in_cell = face_local_numbers_in_their_cells(face_id, 0); + const CellId face_cell_id = face_cell_list[0]; + const size_t face_local_number_in_cell = face_local_numbers_in_their_cells(face_id, 0); const double sign = face_cell_is_reversed(face_cell_id, face_local_number_in_cell) ? -1 : 1; @@ -1693,33 +1568,57 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final } } } - } else if constexpr (std::is_same_v<SymmetryBoundaryCondition, T>) { - // const auto cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix(); - auto is_boundary_node = m_mesh.connectivity().isBoundaryNode(); - - const Rd& n = bc.outgoingNormal(); - const Rdxd I = identity; - const Rdxd nxn = tensorProduct(n, n); - const Rdxd P = I - nxn; - const Array<const NodeId>& node_list = bc.nodeList(); - parallel_for( - bc.numberOfNodes(), PUGS_LAMBDA(int r_number) { - const NodeId r = node_list[r_number]; - b[r] = P * b[r]; - }); + } + }, + boundary_condition); + } - } else if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) { - const auto& node_list = bc.nodeList(); - const auto& value_list = bc.valueList(); + if constexpr (Dimension > 1) { + // axis bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<AxisBoundaryCondition, T>) { + const Rd& t = bc.direction(); + const Rdxd txt = tensorProduct(t, t); + + const auto& node_list = bc.nodeList(); + parallel_for( + bc.numberOfNodes(), PUGS_LAMBDA(const size_t i_node) { + const NodeId node_id = node_list[i_node]; + if (not has_boundary_condition[node_id]) { + b[node_id] = txt * b[node_id]; + + has_boundary_condition[node_id] = true; + } + }); + } + }, + boundary_condition); + } + } + // symmetry bc + for (const auto& boundary_condition : m_boundary_condition_list) { + std::visit( + [&](auto&& bc) { + using T = std::decay_t<decltype(bc)>; + if constexpr (std::is_same_v<SymmetryBoundaryCondition, T>) { + const Rd& n = bc.outgoingNormal(); + const Rdxd I = identity; + const Rdxd nxn = tensorProduct(n, n); + const Rdxd P = I - nxn; + const auto& node_list = bc.nodeList(); parallel_for( - node_list.size(), PUGS_LAMBDA(size_t i_node) { - NodeId node_id = node_list[i_node]; - const auto& value = value_list[i_node]; - b[node_id] = value; + bc.numberOfNodes(), PUGS_LAMBDA(const size_t i_node) { + const NodeId node_id = node_list[i_node]; + if (not has_boundary_condition[node_id]) { + b[node_id] = P * b[node_id]; + + has_boundary_condition[node_id] = true; + } }); - } else { - throw UnexpectedError("boundary condition not handled 5"); } }, boundary_condition); @@ -1835,6 +1734,8 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*mesh); const NodeValuePerCell<const Rd> Cjr_n = mesh_data.Cjr(); + count_Djr = 0; + m_Djr = copy(Cjr_n); CellValue<double> new_rho = copy(rho.cellValues()); @@ -1892,9 +1793,8 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final int number_iter = 0; do { number_iter++; - new_rho = copy(rho.cellValues()); - new_u = copy(u.cellValues()); - new_E = copy(E.cellValues()); + + count_newton = 0; this->_computeGradJU_AU(u, p, pi, dt); @@ -1912,6 +1812,10 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final CellValue<const double> Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); + new_rho = copy(rho.cellValues()); + new_u = copy(u.cellValues()); + new_E = copy(E.cellValues()); + parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId j) { const auto& cell_nodes = cell_to_node_matrix[j]; @@ -1930,19 +1834,33 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final // update Djr const NodeValuePerCell<const Rd> new_Cjr = MeshDataManager::instance().getMeshData(*new_mesh).Cjr(); + CellValue<double> new_Vj{m_mesh.connectivity()}; - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId j) { - new_Vj[j] = 0; - auto cell_nodes = cell_to_node_matrix[j]; + bool is_positive = true; + do { + is_positive = true; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId j) { + new_Vj[j] = 0; + auto cell_nodes = cell_to_node_matrix[j]; - for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) { - const NodeId node_id = cell_nodes[i_node]; - new_Vj[j] += dot(new_Cjr[j][i_node], new_xr[node_id]); - } - new_Vj[j] *= 1. / Dimension; - }); + for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) { + const NodeId node_id = cell_nodes[i_node]; + new_Vj[j] += dot(new_Cjr[j][i_node], new_xr[node_id]); + } + new_Vj[j] *= 1. / Dimension; + }); + + double m = min(new_Vj); + if (m < 0) { + std::cout << "negative volume\n"; + parallel_for( + mesh->numberOfNodes(), + PUGS_LAMBDA(const NodeId node_id) { new_xr[node_id] = 0.5 * (new_xr[node_id] + mesh->xr()[node_id]); }); + is_positive = false; + } + } while (not is_positive); parallel_for( mesh->numberOfCells(), PUGS_LAMBDA(CellId j) { new_rho[j] *= Vj[j] / new_Vj[j]; }); @@ -2011,10 +1929,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final for (size_t r = 0; r < nb_nodes; ++r) { Rd Nr = zero; for (size_t s = 0; s < nb_nodes; ++s) { - const Rd two_dxs = 2 * dxr_n[s]; - Nr += - crossProduct(2 * ((dxr_np1[r] - 2 * dxr_np1[s]) - (dxr_n[r] - 2 * dxr_n[s])), xr_n[face_nodes[s]]); - Nr -= crossProduct((1. / 6) * ((2 * dxr_n[r] - dxr_n[s]) - (2 * dxr_n[r] - dxr_n[s])), + Nr -= crossProduct((1. / 6) * (2 * (dxr_np1[r] - dxr_n[r]) - (dxr_np1[s] - dxr_n[s])), xr_np1[face_nodes[s]] - xr_n[face_nodes[s]]); } Nr *= inv_12_nb_nodes; @@ -2077,12 +1992,31 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final }); m_Djr = Djr; + + double max_err = 0; + + for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) { + if (m_is_implicit_cell[cell_id]) { + double delta_V = new_Vj[cell_id] - Vj[cell_id]; + const auto& node_list = cell_to_node_matrix[cell_id]; + for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { + const NodeId node_id = node_list[i_node]; + delta_V -= dt * dot(ur[node_id], Djr[cell_id][i_node]); + } + max_err = std::max(max_err, std::abs(delta_V)); + } + } + + std::cout << rang::fgB::yellow << "Max volume err = " << max_err << rang::fg::reset << '\n'; } if constexpr (Dimension > 1) { - std::cout << "number_iter_Djr=" << number_iter << " max_tau_error=" << max_tau_error << '\n'; + std::cout << rang::fgB::magenta << "number_iter_Djr=" << number_iter << " max_tau_error=" << max_tau_error + << rang::fg::reset << '\n'; } + ++count_Djr; + // std::cout << "new rho=" << new_rho << '\n'; } while ((Dimension > 1) and (max_tau_error > 1e-4) and (number_iter < 100)); // std::cout << "prochaine boucle" << '\n'; @@ -2093,6 +2027,8 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final // << " HJ_A=" << HJ_A_t << '\n'; // std::cout << "solver=" << solver_t << " total= " << implicit_t << '\n'; + ++count_timestep; + return {new_mesh, std::make_shared<DiscreteFunctionVariant>(DiscreteScalarFunction{new_mesh, new_rho}), std::make_shared<DiscreteFunctionVariant>(DiscreteVectorFunction{new_mesh, new_u}), std::make_shared<DiscreteFunctionVariant>(DiscreteScalarFunction{new_mesh, new_E})}; @@ -2308,6 +2244,51 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver<Dimension>::Symmetry ~SymmetryBoundaryCondition() = default; }; +template <size_t Dimension> +class ImplicitAcousticSolverHandler::ImplicitAcousticSolver<Dimension>::AxisBoundaryCondition +{ + public: + using Rd = TinyVector<Dimension, double>; + + private: + const MeshLineNodeBoundary<Dimension> m_mesh_line_node_boundary; + + public: + const Rd& + direction() const + { + return m_mesh_line_node_boundary.direction(); + } + + size_t + numberOfNodes() const + { + return m_mesh_line_node_boundary.nodeList().size(); + } + + const Array<const NodeId>& + nodeList() const + { + return m_mesh_line_node_boundary.nodeList(); + } + + AxisBoundaryCondition(const MeshLineNodeBoundary<Dimension>& mesh_line_node_boundary) + : m_mesh_line_node_boundary(mesh_line_node_boundary) + { + ; + } + + ~AxisBoundaryCondition() = default; +}; + +template <> +class ImplicitAcousticSolverHandler::ImplicitAcousticSolver<1>::AxisBoundaryCondition +{ + public: + AxisBoundaryCondition() = default; + ~AxisBoundaryCondition() = default; +}; + ImplicitAcousticSolverHandler::ImplicitAcousticSolverHandler( const SolverType solver_type, const std::shared_ptr<const DiscreteFunctionVariant>& rho,